diff --git a/.github/workflows/ami-release-nix.yml b/.github/workflows/ami-release-nix.yml index 3242a4e1d..10c419fb1 100644 --- a/.github/workflows/ami-release-nix.yml +++ b/.github/workflows/ami-release-nix.yml @@ -78,6 +78,7 @@ jobs: run: | packer init amazon-arm64-nix.pkr.hcl GIT_SHA=${{github.sha}} + # why is postgresql_major defined here instead of where the _three_ other postgresql_* variables are defined? packer build -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${GITHUB_RUN_ID}" -var-file="development-arm.vars.pkr.hcl" -var-file="common-nix.vars.pkr.hcl" -var "ansible_arguments=-e postgresql_major=${POSTGRES_MAJOR_VERSION}" amazon-arm64-nix.pkr.hcl - name: Build AMI stage 2 diff --git a/.github/workflows/qemu-image-build.yml b/.github/workflows/qemu-image-build.yml new file mode 100644 index 000000000..464ee01fe --- /dev/null +++ b/.github/workflows/qemu-image-build.yml @@ -0,0 +1,185 @@ +name: Build QEMU image + +on: + push: + branches: + - develop + - release/* + paths: + - '.github/workflows/qemu-image-build.yml' + - 'qemu-arm64-nix.pkr.hcl' + - 'common-nix.vars.pkr.hcl' + - 'ansible/vars.yml' + workflow_dispatch: + +jobs: + prepare: + runs-on: ubuntu-latest + outputs: + postgres_versions: ${{ steps.set-versions.outputs.postgres_versions }} + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + + - uses: DeterminateSystems/nix-installer-action@main + + - name: Set PostgreSQL versions - only builds pg15 atm + id: set-versions + run: | + VERSIONS=$(nix run nixpkgs#yq -- '.postgres_major[0]' ansible/vars.yml | nix run nixpkgs#jq -- -R -s -c 'split("\n")[:-1]') + echo "postgres_versions=$VERSIONS" >> $GITHUB_OUTPUT + + build: + needs: prepare + strategy: + matrix: + postgres_version: ${{ fromJson(needs.prepare.outputs.postgres_versions) }} + runs-on: arm-native-runner + timeout-minutes: 150 + permissions: + contents: write + packages: write + id-token: write + + steps: + - name: Checkout Repo + uses: actions/checkout@v3 + + - uses: DeterminateSystems/nix-installer-action@main + + - name: Run checks if triggered manually + if: ${{ github.event_name == 'workflow_dispatch' }} + run: | + SUFFIX=$(sudo nix run nixpkgs#yq -- ".postgres_release[\"postgres${{ matrix.postgres_version }}\"]" ansible/vars.yml | sed -E 's/[0-9\.]+(.*)$/\1/') + if [[ -z $SUFFIX ]] ; then + echo "Version must include non-numeric characters if built manually." + exit 1 + fi + + - name: enable KVM support + run: | + sudo chown runner /dev/kvm + sudo chmod 666 /dev/kvm + + - name: Set PostgreSQL version environment variable + run: echo "POSTGRES_MAJOR_VERSION=${{ matrix.postgres_version }}" >> $GITHUB_ENV + + - name: Generate common-nix.vars.pkr.hcl + run: | + curl -L https://github.com/mikefarah/yq/releases/download/v4.45.1/yq_linux_arm64 -o yq && chmod +x yq + PG_VERSION=$(./yq '.postgres_release["postgres'${{ matrix.postgres_version }}'"]' ansible/vars.yml) + PG_VERSION=$(echo $PG_VERSION | tr -d '"') # Remove any surrounding quotes + echo 'postgres-version = "'$PG_VERSION'"' > common-nix.vars.pkr.hcl + echo 'postgres-major-version = "'$POSTGRES_MAJOR_VERSION'"' >> common-nix.vars.pkr.hcl + # Ensure there's a newline at the end of the file + echo "" >> common-nix.vars.pkr.hcl + + # TODO (darora): not quite sure why I'm having to uninstall and re-install these deps, but the build fails w/o this + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get remove -y qemu-efi-aarch64 cloud-image-utils qemu-system-arm qemu-utils + sudo apt-get install -y qemu-efi-aarch64 cloud-image-utils qemu-system-arm qemu-utils + + - name: Build QEMU artifact + run: | + make init + GIT_SHA=${{github.sha}} + export PACKER_LOG=1 + packer build -var "git_sha=${GIT_SHA}" -var-file="common-nix.vars.pkr.hcl" qemu-arm64-nix.pkr.hcl + + - name: Grab release version + id: process_release_version + run: | + VERSION=$(cat common-nix.vars.pkr.hcl | sed -e 's/postgres-version = "\(.*\)"/\1/g') + echo "version=$VERSION" >> $GITHUB_OUTPUT + + # - name: Create nix flake revision tarball + # run: | + # GIT_SHA=${{github.sha}} + # MAJOR_VERSION=${{ env.POSTGRES_MAJOR_VERSION }} + + # mkdir -p "/tmp/pg_upgrade_bin/${MAJOR_VERSION}" + # echo "$GIT_SHA" >> "/tmp/pg_upgrade_bin/${MAJOR_VERSION}/nix_flake_version" + # tar -czf "/tmp/pg_binaries.tar.gz" -C "/tmp/pg_upgrade_bin" . + + - name: configure aws credentials - staging + uses: aws-actions/configure-aws-credentials@v4 + with: + role-to-assume: ${{ secrets.DEV_AWS_ROLE }} + aws-region: "us-east-1" + + - name: Login to Amazon ECR Public + id: login-ecr-public + uses: aws-actions/amazon-ecr-login@v2 + with: + registry-type: public + + - name: Build, tag, and push docker image to Amazon ECR Public + env: + REGISTRY: public.ecr.aws/w9p6e7k7 + REGISTRY_ALIAS: supabase + REPOSITORY: postgres-vm-image + IMAGE_TAG: ${{ steps.process_release_version.outputs.version }} + run: | + docker build -f Dockerfile-kubernetes -t $REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG . + docker push $REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG + + # - name: Upload software manifest to s3 staging + # run: | + # cd ansible + # ansible-playbook -i localhost \ + # -e "ami_release_version=${{ steps.process_release_version.outputs.version }}" \ + # -e "internal_artifacts_bucket=${{ secrets.ARTIFACTS_BUCKET }}" \ + # -e "postgres_major_version=${{ env.POSTGRES_MAJOR_VERSION }}" \ + # manifest-playbook.yml + + # - name: Upload nix flake revision to s3 staging + # run: | + # aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz + + # - name: configure aws credentials - prod + # uses: aws-actions/configure-aws-credentials@v4 + # with: + # role-to-assume: ${{ secrets.PROD_AWS_ROLE }} + # aws-region: "us-east-1" + + # - name: Upload software manifest to s3 prod + # run: | + # cd ansible + # ansible-playbook -i localhost \ + # -e "ami_release_version=${{ steps.process_release_version.outputs.version }}" \ + # -e "internal_artifacts_bucket=${{ secrets.PROD_ARTIFACTS_BUCKET }}" \ + # -e "postgres_major_version=${{ env.POSTGRES_MAJOR_VERSION }}" \ + # manifest-playbook.yml + + # - name: Upload nix flake revision to s3 prod + # run: | + # aws s3 cp /tmp/pg_binaries.tar.gz s3://${{ secrets.PROD_ARTIFACTS_BUCKET }}/upgrades/postgres/supabase-postgres-${{ steps.process_release_version.outputs.version }}/20.04.tar.gz + + # - name: Create release + # uses: softprops/action-gh-release@v1 + # with: + # name: ${{ steps.process_release_version.outputs.version }} + # tag_name: ${{ steps.process_release_version.outputs.version }} + # target_commitish: ${{github.sha}} + + # - name: Slack Notification on Failure + # if: ${{ failure() }} + # uses: rtCamp/action-slack-notify@v2 + # env: + # SLACK_WEBHOOK: ${{ secrets.SLACK_NOTIFICATIONS_WEBHOOK }} + # SLACK_USERNAME: 'gha-failures-notifier' + # SLACK_COLOR: 'danger' + # SLACK_MESSAGE: 'Building Postgres AMI failed' + # SLACK_FOOTER: '' + + - name: Cleanup resources after build + if: ${{ always() }} + run: | + aws ec2 describe-instances --filters "Name=tag:packerExecutionId,Values=${GITHUB_RUN_ID}" --query "Reservations[].Instances[].InstanceId" --output text | xargs -r aws ec2 terminate-instances --instance-ids + + - name: Cleanup resources on build cancellation + if: ${{ cancelled() }} + run: | + aws ec2 describe-instances --filters "Name=tag:packerExecutionId,Values=${GITHUB_RUN_ID}" --query "Reservations[].Instances[].InstanceId" --output text | xargs -r aws ec2 terminate-instances --instance-ids diff --git a/Dockerfile-kubernetes b/Dockerfile-kubernetes new file mode 100644 index 000000000..716e72b42 --- /dev/null +++ b/Dockerfile-kubernetes @@ -0,0 +1,9 @@ +FROM alpine:3.21 + +ADD ./output-cloudimg/packer-cloudimg /disk/focal.qcow2 + +RUN apk add --no-cache qemu-system-aarch64 qemu-img openssh-client nftables cloud-utils-localds aavmf +# dev stuff +# RUN apk add --no-cache iproute2 + +CMD exec /bin/sh -c "trap : TERM INT; sleep 9999999999d & wait" diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..5bef8a430 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +UPSTREAM_NIX_GIT_SHA := $(shell git rev-parse HEAD) +GIT_SHA := $(shell git describe --tags --always --dirty) + +init: qemu-arm64-nix.pkr.hcl + packer init qemu-arm64-nix.pkr.hcl + +output-cloudimg/packer-cloudimg: ansible qemu-arm64-nix.pkr.hcl + packer build -var "git_sha=$(UPSTREAM_NIX_GIT_SHA)" qemu-arm64-nix.pkr.hcl + +disk/focal-raw.img: output-cloudimg/packer-cloudimg + mkdir -p disk + sudo qemu-img convert -O raw output-cloudimg/packer-cloudimg disk/focal-raw.img + +alpine-image: output-cloudimg/packer-cloudimg + sudo nerdctl build . -t supabase-postgres-test:$(GIT_SHA) -f ./Dockerfile-kubernetes + +clean: + rm -rf output-cloudimg + +.PHONY: alpine-image init clean diff --git a/amazon-arm64-nix.pkr.hcl b/amazon-arm64-nix.pkr.hcl index 118196473..ec427ff9f 100644 --- a/amazon-arm64-nix.pkr.hcl +++ b/amazon-arm64-nix.pkr.hcl @@ -264,7 +264,7 @@ build { ] use_env_var_file = true script = "ebssurrogate/scripts/surrogate-bootstrap-nix.sh" - execute_command = "sudo -S sh -c '. {{.EnvVarFile}} && {{.Path}}'" + execute_command = "sudo -S sh -c '. {{.EnvVarFile}} && cd /tmp/ansible-playbook && {{.Path}}'" start_retry_timeout = "5m" skip_clean = true } diff --git a/ansible/files/permission_check.py b/ansible/files/permission_check.py index 724acb10a..5bf421018 100644 --- a/ansible/files/permission_check.py +++ b/ansible/files/permission_check.py @@ -1,155 +1,110 @@ import subprocess import json import sys +import argparse + # Expected groups for each user expected_results = { "postgres": [ {"groupname": "postgres", "username": "postgres"}, - {"groupname": "ssl-cert", "username": "postgres"} + {"groupname": "ssl-cert", "username": "postgres"}, ], "ubuntu": [ - {"groupname":"ubuntu","username":"ubuntu"}, - {"groupname":"adm","username":"ubuntu"}, - {"groupname":"dialout","username":"ubuntu"}, - {"groupname":"cdrom","username":"ubuntu"}, - {"groupname":"floppy","username":"ubuntu"}, - {"groupname":"sudo","username":"ubuntu"}, - {"groupname":"audio","username":"ubuntu"}, - {"groupname":"dip","username":"ubuntu"}, - {"groupname":"video","username":"ubuntu"}, - {"groupname":"plugdev","username":"ubuntu"}, - {"groupname":"lxd","username":"ubuntu"}, - {"groupname":"netdev","username":"ubuntu"} - ], - "root": [ - {"groupname":"root","username":"root"} - ], - "daemon": [ - {"groupname":"daemon","username":"daemon"} - ], - "bin": [ - {"groupname":"bin","username":"bin"} - ], - "sys": [ - {"groupname":"sys","username":"sys"} - ], - "sync": [ - {"groupname":"nogroup","username":"sync"} - ], - "games": [ - {"groupname":"games","username":"games"} - ], - "man": [ - {"groupname":"man","username":"man"} - ], - "lp": [ - {"groupname":"lp","username":"lp"} - ], - "mail": [ - {"groupname":"mail","username":"mail"} - ], - "news": [ - {"groupname":"news","username":"news"} - ], - "uucp": [ - {"groupname":"uucp","username":"uucp"} - ], - "proxy": [ - {"groupname":"proxy","username":"proxy"} - ], - "www-data": [ - {"groupname":"www-data","username":"www-data"} - ], - "backup": [ - {"groupname":"backup","username":"backup"} - ], - "list": [ - {"groupname":"list","username":"list"} - ], - "irc": [ - {"groupname":"irc","username":"irc"} - ], - "gnats": [ - {"groupname":"gnats","username":"gnats"} - ], - "nobody": [ - {"groupname":"nogroup","username":"nobody"} - ], + {"groupname": "adm", "username": "ubuntu"}, + {"groupname": "audio", "username": "ubuntu"}, + {"groupname": "cdrom", "username": "ubuntu"}, + {"groupname": "dialout", "username": "ubuntu"}, + {"groupname": "dip", "username": "ubuntu"}, + {"groupname": "floppy", "username": "ubuntu"}, + {"groupname": "lxd", "username": "ubuntu"}, + {"groupname": "netdev", "username": "ubuntu"}, + {"groupname": "plugdev", "username": "ubuntu"}, + {"groupname": "sudo", "username": "ubuntu"}, + {"groupname": "ubuntu", "username": "ubuntu"}, + {"groupname": "video", "username": "ubuntu"}, + ], + "root": [{"groupname": "root", "username": "root"}], + "daemon": [{"groupname": "daemon", "username": "daemon"}], + "bin": [{"groupname": "bin", "username": "bin"}], + "sys": [{"groupname": "sys", "username": "sys"}], + "sync": [{"groupname": "nogroup", "username": "sync"}], + "games": [{"groupname": "games", "username": "games"}], + "man": [{"groupname": "man", "username": "man"}], + "lp": [{"groupname": "lp", "username": "lp"}], + "mail": [{"groupname": "mail", "username": "mail"}], + "news": [{"groupname": "news", "username": "news"}], + "uucp": [{"groupname": "uucp", "username": "uucp"}], + "proxy": [{"groupname": "proxy", "username": "proxy"}], + "www-data": [{"groupname": "www-data", "username": "www-data"}], + "backup": [{"groupname": "backup", "username": "backup"}], + "list": [{"groupname": "list", "username": "list"}], + "irc": [{"groupname": "irc", "username": "irc"}], + "gnats": [{"groupname": "gnats", "username": "gnats"}], + "nobody": [{"groupname": "nogroup", "username": "nobody"}], "systemd-network": [ - {"groupname":"systemd-network","username":"systemd-network"} + {"groupname": "systemd-network", "username": "systemd-network"} ], "systemd-resolve": [ - {"groupname":"systemd-resolve","username":"systemd-resolve"} + {"groupname": "systemd-resolve", "username": "systemd-resolve"} ], "systemd-timesync": [ - {"groupname":"systemd-timesync","username":"systemd-timesync"} - ], - "messagebus": [ - {"groupname":"messagebus","username":"messagebus"} + {"groupname": "systemd-timesync", "username": "systemd-timesync"} ], + "messagebus": [{"groupname": "messagebus", "username": "messagebus"}], "ec2-instance-connect": [ - {"groupname":"nogroup","username":"ec2-instance-connect"} - ], - "sshd": [ - {"groupname":"nogroup","username":"sshd"} + {"groupname": "nogroup", "username": "ec2-instance-connect"} ], + "sshd": [{"groupname": "nogroup", "username": "sshd"}], "wal-g": [ - {"groupname":"wal-g","username":"wal-g"}, - {"groupname":"postgres","username":"wal-g"} + {"groupname": "postgres", "username": "wal-g"}, + {"groupname": "wal-g", "username": "wal-g"}, ], "pgbouncer": [ - {"groupname":"pgbouncer","username":"pgbouncer"}, - {"groupname":"ssl-cert","username":"pgbouncer"}, - {"groupname":"postgres","username":"pgbouncer"} - ], - "gotrue": [ - {"groupname":"gotrue","username":"gotrue"} - ], - "envoy": [ - {"groupname":"envoy","username":"envoy"} - ], - "kong": [ - {"groupname":"kong","username":"kong"} - ], - "nginx": [ - {"groupname":"nginx","username":"nginx"} - ], + {"groupname": "pgbouncer", "username": "pgbouncer"}, + {"groupname": "postgres", "username": "pgbouncer"}, + {"groupname": "ssl-cert", "username": "pgbouncer"}, + ], + "gotrue": [{"groupname": "gotrue", "username": "gotrue"}], + "envoy": [{"groupname": "envoy", "username": "envoy"}], + "kong": [{"groupname": "kong", "username": "kong"}], + "nginx": [{"groupname": "nginx", "username": "nginx"}], "vector": [ - {"groupname":"vector","username":"vector"}, - {"groupname":"adm","username":"vector"}, - {"groupname":"systemd-journal","username":"vector"}, - {"groupname":"postgres","username":"vector"} + {"groupname": "adm", "username": "vector"}, + {"groupname": "postgres", "username": "vector"}, + {"groupname": "systemd-journal", "username": "vector"}, + {"groupname": "vector", "username": "vector"}, ], "adminapi": [ - {"groupname":"adminapi","username":"adminapi"}, - {"groupname":"root","username":"adminapi"}, - {"groupname":"systemd-journal","username":"adminapi"}, - {"groupname":"admin","username":"adminapi"}, - {"groupname":"postgres","username":"adminapi"}, - {"groupname":"pgbouncer","username":"adminapi"}, - {"groupname":"wal-g","username":"adminapi"}, - {"groupname":"postgrest","username":"adminapi"}, - {"groupname":"envoy","username":"adminapi"}, - {"groupname":"kong","username":"adminapi"}, - {"groupname":"vector","username":"adminapi"} - ], - "postgrest": [ - {"groupname":"postgrest","username":"postgrest"} - ], - "tcpdump": [ - {"groupname":"tcpdump","username":"tcpdump"} - ], + {"groupname": "admin", "username": "adminapi"}, + {"groupname": "adminapi", "username": "adminapi"}, + {"groupname": "envoy", "username": "adminapi"}, + {"groupname": "kong", "username": "adminapi"}, + {"groupname": "pgbouncer", "username": "adminapi"}, + {"groupname": "postgres", "username": "adminapi"}, + {"groupname": "postgrest", "username": "adminapi"}, + {"groupname": "root", "username": "adminapi"}, + {"groupname": "systemd-journal", "username": "adminapi"}, + {"groupname": "vector", "username": "adminapi"}, + {"groupname": "wal-g", "username": "adminapi"}, + ], + "postgrest": [{"groupname": "postgrest", "username": "postgrest"}], + "tcpdump": [{"groupname": "tcpdump", "username": "tcpdump"}], "systemd-coredump": [ - {"groupname":"systemd-coredump","username":"systemd-coredump"} - ] + {"groupname": "systemd-coredump", "username": "systemd-coredump"} + ], } + + # This program depends on osquery being installed on the system # Function to run osquery def run_osquery(query): - process = subprocess.Popen(['osqueryi', '--json', query], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + process = subprocess.Popen( + ["osqueryi", "--json", query], stdout=subprocess.PIPE, stderr=subprocess.PIPE + ) output, error = process.communicate() - return output.decode('utf-8') + return output.decode("utf-8") + def parse_json(json_str): try: @@ -158,6 +113,7 @@ def parse_json(json_str): print("Error decoding JSON:", e) sys.exit(1) + def compare_results(username, query_result): expected_result = expected_results.get(username) if expected_result is None: @@ -167,38 +123,101 @@ def compare_results(username, query_result): if query_result == expected_result: print(f"The query result for user '{username}' matches the expected result.") else: - print(f"The query result for user '{username}' does not match the expected result.") + print( + f"The query result for user '{username}' does not match the expected result." + ) print("Expected:", expected_result) print("Got:", query_result) sys.exit(1) + def check_nixbld_users(): query = """ - SELECT u.username, g.groupname - FROM users u - JOIN user_groups ug ON u.uid = ug.uid - JOIN groups g ON ug.gid = g.gid + SELECT u.username, g.groupname + FROM users u + JOIN user_groups ug ON u.uid = ug.uid + JOIN groups g ON ug.gid = g.gid WHERE u.username LIKE 'nixbld%'; """ query_result = run_osquery(query) parsed_result = parse_json(query_result) - + for user in parsed_result: - if user['groupname'] != 'nixbld': - print(f"User '{user['username']}' is in group '{user['groupname']}' instead of 'nixbld'.") + if user["groupname"] != "nixbld": + print( + f"User '{user['username']}' is in group '{user['groupname']}' instead of 'nixbld'." + ) sys.exit(1) - + print("All nixbld users are in the 'nixbld' group.") -# Define usernames for which you want to compare results -usernames = ["postgres", "ubuntu", "root", "daemon", "bin", "sys", "sync", "games","man","lp","mail","news","uucp","proxy","www-data","backup","list","irc","gnats","nobody","systemd-network","systemd-resolve","systemd-timesync","messagebus","ec2-instance-connect","sshd","wal-g","pgbouncer","gotrue","envoy","kong","nginx","vector","adminapi","postgrest","tcpdump","systemd-coredump"] -# Iterate over usernames, run the query, and compare results -for username in usernames: - query = f"SELECT u.username, g.groupname FROM users u JOIN user_groups ug ON u.uid = ug.uid JOIN groups g ON ug.gid = g.gid WHERE u.username = '{username}';" - query_result = run_osquery(query) - parsed_result = parse_json(query_result) - compare_results(username, parsed_result) +def main(): + parser = argparse.ArgumentParser( + prog="Supabase Postgres Artifact Permissions Checker", + description="Checks the Postgres Artifact for the appropriate users and group memberships", + ) + parser.add_argument( + "-q", + "--qemu", + action="store_true", + help="Whether we are checking a QEMU artifact", + ) + args = parser.parse_args() + qemu_artifact = args.qemu or False + + # Define usernames for which you want to compare results + usernames = [ + "postgres", + "ubuntu", + "root", + "daemon", + "bin", + "sys", + "sync", + "games", + "man", + "lp", + "mail", + "news", + "uucp", + "proxy", + "www-data", + "backup", + "list", + "irc", + "gnats", + "nobody", + "systemd-network", + "systemd-resolve", + "systemd-timesync", + "messagebus", + "sshd", + "wal-g", + "pgbouncer", + "gotrue", + "envoy", + "kong", + "nginx", + "vector", + "adminapi", + "postgrest", + "tcpdump", + "systemd-coredump", + ] + if not qemu_artifact: + usernames.append("ec2-instance-connect") + + # Iterate over usernames, run the query, and compare results + for username in usernames: + query = f"SELECT u.username, g.groupname FROM users u JOIN user_groups ug ON u.uid = ug.uid JOIN groups g ON ug.gid = g.gid WHERE u.username = '{username}' ORDER BY g.groupname;" + query_result = run_osquery(query) + parsed_result = parse_json(query_result) + compare_results(username, parsed_result) + + # Check if all nixbld users are in the nixbld group + check_nixbld_users() + -# Check if all nixbld users are in the nixbld group -check_nixbld_users() +if __name__ == "__main__": + main() diff --git a/ansible/playbook.yml b/ansible/playbook.yml index a6bea19e9..5c5f8da3a 100644 --- a/ansible/playbook.yml +++ b/ansible/playbook.yml @@ -142,6 +142,7 @@ import_tasks: tasks/setup-fail2ban.yml when: debpkg_mode or nixpkg_mode + # Install EC2 instance connect # Only for AWS images - name: install EC2 instance connect @@ -151,6 +152,7 @@ - ec2-instance-connect tags: - aws-only + when: qemu_mode is undefined # Install this at the end to prevent it from kicking in during the apt process, causing conflicts - name: Install security tools @@ -196,6 +198,12 @@ - collect-binaries when: debpkg_mode + - name: Install osquery from nixpkgs binary cache + become: yes + shell: | + apt autoremove -y --purge snapd + when: stage2_nix + - name: Install osquery from nixpkgs binary cache become: yes shell: | @@ -205,7 +213,7 @@ - name: Run osquery permission checks become: yes shell: | - sudo -u ubuntu bash -c ". /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && /usr/bin/python3 /tmp/ansible-playbook/ansible/files/permission_check.py" + sudo -u ubuntu bash -c ". /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh && /usr/bin/python3 /tmp/ansible-playbook/ansible/files/permission_check.py {{ '--qemu' if qemu_mode is defined else '' }}" when: stage2_nix - name: Remove osquery diff --git a/ansible/tasks/setup-fail2ban.yml b/ansible/tasks/setup-fail2ban.yml index 1f6065d32..7d9088d46 100644 --- a/ansible/tasks/setup-fail2ban.yml +++ b/ansible/tasks/setup-fail2ban.yml @@ -65,16 +65,9 @@ - install-supabase-internal when: debpkg_mode or nixpkg_mode -# Restart -- name: fail2ban - restart - systemd: - name: fail2ban - state: restarted - when: debpkg_mode or nixpkg_mode - - name: fail2ban - disable service systemd: name: fail2ban enabled: no daemon_reload: yes - when: debpkg_mode or nixpkg_mode \ No newline at end of file + when: debpkg_mode or nixpkg_mode diff --git a/ansible/tasks/setup-postgres.yml b/ansible/tasks/setup-postgres.yml index 188a364b8..a45b7a502 100644 --- a/ansible/tasks/setup-postgres.yml +++ b/ansible/tasks/setup-postgres.yml @@ -204,6 +204,14 @@ ansible_command_timeout: 60 when: debpkg_mode +- name: Make sure .bashrc exists + file: + path: /var/lib/postgresql/.bashrc + state: touch + owner: postgres + group: postgres + when: nixpkg_mode + - name: Check psql_version and modify supautils.conf and postgresql.conf if necessary block: - name: Check if psql_version is psql_orioledb @@ -260,6 +268,13 @@ dest: /etc/systemd/system/database-optimizations.service when: debpkg_mode or stage2_nix +- name: initialize pg required state + become: yes + shell: | + mkdir -p /run/postgresql + chown -R postgres:postgres /run/postgresql + when: stage2_nix and qemu_mode is defined + - name: Restart Postgres Database without Systemd become: yes become_user: postgres @@ -283,13 +298,6 @@ daemon_reload: yes when: debpkg_mode or stage2_nix -- name: Make sure .bashrc exists - file: - path: /var/lib/postgresql/.bashrc - state: touch - owner: postgres - group: postgres - when: nixpkg_mode - name: Add LOCALE_ARCHIVE to .bashrc lineinfile: diff --git a/ansible/tasks/stage2-setup-postgres.yml b/ansible/tasks/stage2-setup-postgres.yml index facc1e54d..d2877e239 100644 --- a/ansible/tasks/stage2-setup-postgres.yml +++ b/ansible/tasks/stage2-setup-postgres.yml @@ -164,7 +164,7 @@ - name: import pgsodium_getkey script template: - src: /tmp/ansible-playbook/ansible/files/pgsodium_getkey_readonly.sh.j2 + src: files/pgsodium_getkey_readonly.sh.j2 dest: "/usr/lib/postgresql/bin/pgsodium_getkey.sh" owner: postgres group: postgres @@ -172,12 +172,11 @@ when: stage2_nix - name: Create symbolic links from /var/lib/postgresql/.nix-profile/bin to /usr/lib/postgresql/bin - file: - src: "{{ item }}" - dest: "/usr/lib/postgresql/bin/{{ item | basename }}" - state: link - with_fileglob: - - "/var/lib/postgresql/.nix-profile/bin/*" + shell: >- + find /var/lib/postgresql/.nix-profile/bin/ -maxdepth 1 -type f,l -exec sh -c 'ln -s "$0" "{{ item }}/$(basename $0)"' {} \; + loop: + - /usr/lib/postgresql/bin + - /usr/bin become: yes when: stage2_nix @@ -194,23 +193,9 @@ when: pg_config_stat.stat.exists and not pg_config_stat.stat.islnk and stage2_nix become: yes -- name: Create symbolic links from /var/lib/postgresql/.nix-profile/bin to /usr/bin - file: - src: "{{ item }}" - dest: "/usr/bin/{{ item | basename }}" - state: link - with_fileglob: - - "/var/lib/postgresql/.nix-profile/bin/*" - become: yes - when: stage2_nix - - name: Ensure postgres user has ownership of symlink - file: - path: "/usr/bin/{{ item | basename }}" - owner: postgres - group: postgres - with_fileglob: - - "/var/lib/postgresql/.nix-profile/bin/*" + shell: >- + find /var/lib/postgresql/.nix-profile/bin/ -maxdepth 1 -type f,l -exec chown postgres:postgres "/usr/bin/$(basename {})" \; become: yes when: stage2_nix @@ -225,22 +210,14 @@ # It was decided to leave pljava disabled at https://github.com/supabase/postgres/pull/690 therefore removing this task - name: Create symbolic links from /var/lib/postgresql/.nix-profile/share/postgresql to /usr/lib/postgresql/share/postgresql - file: - src: "{{ item }}" - dest: "/usr/lib/postgresql/share/postgresql/{{ item | basename }}" - state: link - with_fileglob: - - "/var/lib/postgresql/.nix-profile/share/postgresql/*" + shell: >- + find /var/lib/postgresql/.nix-profile/share/postgresql/ -maxdepth 1 -type f,l -exec sh -c 'ln -s "$0" "/usr/lib/postgresql/share/postgresql/$(basename $0)"' {} \; become: yes when: stage2_nix - name: Create symbolic links from /var/lib/postgresql/.nix-profile/share/postgresql/extension to /usr/lib/postgresql/share/postgresql/extension - file: - src: "{{ item }}" - dest: "/usr/lib/postgresql/share/postgresql/extension/{{ item | basename }}" - state: link - with_fileglob: - - "/var/lib/postgresql/.nix-profile/share/postgresql/extension/*" + shell: >- + find /var/lib/postgresql/.nix-profile/share/postgresql/extension/ -maxdepth 1 -type f,l -exec sh -c 'ln -s "$0" "/usr/lib/postgresql/share/postgresql/extension/$(basename $0)"' {} \; become: yes when: stage2_nix @@ -266,22 +243,14 @@ when: stage2_nix and not is_psql_oriole - name: Create symbolic links from /var/lib/postgresql/.nix-profile/share/postgresql/timezonesets to /usr/lib/postgresql/share/postgresql/timeszonesets - file: - src: "{{ item }}" - dest: "/usr/lib/postgresql/share/postgresql/timezonesets/{{ item | basename }}" - state: link - with_fileglob: - - "/var/lib/postgresql/.nix-profile/share/postgresql/timezonesets/*" + shell: >- + find /var/lib/postgresql/.nix-profile/share/postgresql/timezonesets/ -maxdepth 1 -type f,l -exec sh -c 'ln -s "$0" "/usr/lib/postgresql/share/postgresql/timezonesets/$(basename $0)"' {} \; become: yes when: stage2_nix - name: Create symbolic links from /var/lib/postgresql/.nix-profile/share/postgresql/tsearch_data to /usr/lib/postgresql/share/postgresql/tsearch_data - file: - src: "{{ item }}" - dest: "/usr/lib/postgresql/share/postgresql/tsearch_data/{{ item | basename }}" - state: link - with_fileglob: - - "/var/lib/postgresql/.nix-profile/share/postgresql/tsearch_data/*" + shell: >- + find /var/lib/postgresql/.nix-profile/share/postgresql/tsearch_data/ -maxdepth 1 -type f,l -exec sh -c 'ln -s "$0" "/usr/lib/postgresql/share/postgresql/tsearch_data/$(basename $0)"' {} \; become: yes when: stage2_nix diff --git a/ansible/vars.yml b/ansible/vars.yml index 95bc674d2..40c2e2788 100644 --- a/ansible/vars.yml +++ b/ansible/vars.yml @@ -25,7 +25,7 @@ postgrest_x86_release_checksum: sha1:61c513f91a8931be4062587b9d4a18b42acf5c05 gotrue_release: 2.169.0 gotrue_release_checksum: sha1:1419b94683aac7ddc30355408b8e8b79e61146c4 -aws_cli_release: "2.2.7" +aws_cli_release: "2.23.11" salt_minion_version: 3007 diff --git a/ebssurrogate/scripts/qemu-bootstrap-nix.sh b/ebssurrogate/scripts/qemu-bootstrap-nix.sh new file mode 100755 index 000000000..61606c81e --- /dev/null +++ b/ebssurrogate/scripts/qemu-bootstrap-nix.sh @@ -0,0 +1,146 @@ +#!/usr/bin/env bash + +set -o errexit +set -o pipefail +set -o xtrace + +if [ $(dpkg --print-architecture) = "amd64" ]; then + ARCH="amd64" +else + ARCH="arm64" +fi + +function waitfor_boot_finished { + export DEBIAN_FRONTEND=noninteractive + + echo "args: ${ARGS}" + # Wait for cloudinit on the surrogate to complete before making progress + while [[ ! -f /var/lib/cloud/instance/boot-finished ]]; do + echo 'Waiting for cloud-init...' + sleep 1 + done +} + +function install_packages { + apt-get update && sudo apt-get install software-properties-common e2fsprogs -y + add-apt-repository --yes --update ppa:ansible/ansible && sudo apt-get install ansible -y + ansible-galaxy collection install community.general +} + +function execute_playbook { + + tee /etc/ansible/ansible.cfg </dev/null +LOCALE_ARCHIVE=/usr/lib/locale/locale-archive +LANG="en_US.UTF-8" +LANGUAGE="en_US.UTF-8" +LC_ALL="en_US.UTF-8" +LC_CTYPE="en_US.UTF-8" +EOF +} + +function setup_locale { + cat <>/etc/locale.gen +en_US.UTF-8 UTF-8 +EOF + + cat </etc/default/locale +LANG="C.UTF-8" +LC_CTYPE="C.UTF-8" +EOF + locale-gen en_US.UTF-8 +} + +sed -i 's/- hosts: all/- hosts: localhost/' ansible/playbook.yml + +waitfor_boot_finished +install_packages +setup_postgesql_env +setup_locale +execute_playbook + +#################### +# stage 2 things +#################### + +function install_nix() { + sudo su -c "curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --no-confirm \ + --extra-conf \"substituters = https://cache.nixos.org https://nix-postgres-artifacts.s3.amazonaws.com\" \ + --extra-conf \"trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI=% cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=\" " -s /bin/bash root + . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh + +} + +function execute_stage2_playbook { + sudo tee /etc/ansible/ansible.cfg < /root/.bash_history +unset HISTFILE +find /var/log -mtime -1 -type f -exec truncate -s 0 {} \; +rm -rf /var/log/*.gz /var/log/*.[0-9] /var/log/*-???????? +rm -rf /var/lib/cloud/instances/* +rm -f /root/.ssh/authorized_keys /etc/ssh/*key* +touch /etc/ssh/revoked_keys +chmod 600 /etc/ssh/revoked_keys + +cat /dev/null > /var/log/lastlog +cat /dev/null > /var/log/wtmp diff --git a/user-data-cloudimg b/user-data-cloudimg new file mode 100644 index 000000000..9a74d237a --- /dev/null +++ b/user-data-cloudimg @@ -0,0 +1,16 @@ +#cloud-config +users: + - name: root + lock_passwd: false + ssh_redirect_user: true + hashed_passwd: "$6$canonical.$0zWaW71A9ke9ASsaOcFTdQ2tx1gSmLxMPrsH0rF0Yb.2AEKNPV1lrF94n6YuPJmnUy2K2/JSDtxuiBDey6Lpa/" + - name: ubuntu + lock_passwd: false + hashed_passwd: "$6$canonical.$0zWaW71A9ke9ASsaOcFTdQ2tx1gSmLxMPrsH0rF0Yb.2AEKNPV1lrF94n6YuPJmnUy2K2/JSDtxuiBDey6Lpa/" + ssh_redired_user: false + sudo: "ALL=(ALL) NOPASSWD:ALL" + shell: /usr/bin/bash + groups: [adm, audio, cdrom, dialout, dip, floppy, lxd, netdev, plugdev, sudo, video] +ssh_pwauth: True +disable_root: false +preserve_hostname: true