From fa4ef5d31315f4f57860a1a62732575ffa95ae8d Mon Sep 17 00:00:00 2001 From: Sohan Kshirsagar Date: Mon, 16 Mar 2026 18:21:59 -0700 Subject: [PATCH 1/4] test: enforce strict replay sandboxing in e2e fixtures --- .../aiohttp/e2e-tests/.tusk/config.yaml | 2 + .../aiohttp/e2e-tests/docker-compose.yml | 5 ++ .../django/e2e-tests/.tusk/config.yaml | 2 + .../django/e2e-tests/docker-compose.yml | 5 ++ .../e2e_common/Dockerfile.base | 58 ++++++++++--------- .../fastapi/e2e-tests/.tusk/config.yaml | 2 + .../fastapi/e2e-tests/docker-compose.yml | 5 ++ .../fastapi/e2e-tests/requirements.txt | 3 +- .../flask/e2e-tests/.tusk/config.yaml | 2 + .../flask/e2e-tests/docker-compose.yml | 5 ++ .../grpc/e2e-tests/.tusk/config.yaml | 2 + .../grpc/e2e-tests/docker-compose.yml | 5 ++ .../grpc/e2e-tests/src/greeter_pb2_grpc.py | 2 +- .../httpx/e2e-tests/.tusk/config.yaml | 2 + .../httpx/e2e-tests/docker-compose.yml | 5 ++ .../httpx/e2e-tests/requirements.txt | 3 +- .../psycopg/e2e-tests/.tusk/config.yaml | 2 + .../psycopg/e2e-tests/docker-compose.yml | 5 ++ .../psycopg2/e2e-tests/.tusk/config.yaml | 2 + .../psycopg2/e2e-tests/docker-compose.yml | 5 ++ .../redis/e2e-tests/.tusk/config.yaml | 2 + .../redis/e2e-tests/docker-compose.yml | 5 ++ .../requests/e2e-tests/.tusk/config.yaml | 2 + .../requests/e2e-tests/docker-compose.yml | 5 ++ .../sqlalchemy/e2e-tests/.tusk/config.yaml | 2 + .../sqlalchemy/e2e-tests/docker-compose.yml | 5 ++ .../sqlalchemy/e2e-tests/run.sh | 0 .../urllib/e2e-tests/.tusk/config.yaml | 2 + .../urllib/e2e-tests/docker-compose.yml | 5 ++ .../urllib3/e2e-tests/.tusk/config.yaml | 2 + .../urllib3/e2e-tests/docker-compose.yml | 5 ++ .../django-postgres/.tusk/config.yaml | 4 ++ .../django-postgres/docker-compose.yml | 5 ++ .../django-redis/.tusk/config.yaml | 4 ++ .../django-redis/docker-compose.yml | 5 ++ .../fastapi-postgres/.tusk/config.yaml | 4 ++ .../fastapi-postgres/docker-compose.yml | 5 ++ .../fastapi-sqlalchemy/.tusk/config.yaml | 4 ++ .../fastapi-sqlalchemy/docker-compose.yml | 5 ++ drift/stack-tests/fastapi-sqlalchemy/run.sh | 0 40 files changed, 162 insertions(+), 31 deletions(-) mode change 100644 => 100755 drift/instrumentation/sqlalchemy/e2e-tests/run.sh mode change 100644 => 100755 drift/stack-tests/fastapi-sqlalchemy/run.sh diff --git a/drift/instrumentation/aiohttp/e2e-tests/.tusk/config.yaml b/drift/instrumentation/aiohttp/e2e-tests/.tusk/config.yaml index c98214b..7d40a7d 100644 --- a/drift/instrumentation/aiohttp/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/aiohttp/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/aiohttp/e2e-tests/docker-compose.yml b/drift/instrumentation/aiohttp/e2e-tests/docker-compose.yml index 2989a5c..14976cb 100644 --- a/drift/instrumentation/aiohttp/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/aiohttp/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/aiohttp/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/django/e2e-tests/.tusk/config.yaml b/drift/instrumentation/django/e2e-tests/.tusk/config.yaml index c39e52e..ec41d3a 100644 --- a/drift/instrumentation/django/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/django/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/django/e2e-tests/docker-compose.yml b/drift/instrumentation/django/e2e-tests/docker-compose.yml index b466d23..801a3c7 100644 --- a/drift/instrumentation/django/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/django/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/django/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/e2e_common/Dockerfile.base b/drift/instrumentation/e2e_common/Dockerfile.base index c05b64a..303af74 100644 --- a/drift/instrumentation/e2e_common/Dockerfile.base +++ b/drift/instrumentation/e2e_common/Dockerfile.base @@ -3,7 +3,7 @@ # This base image contains: # - Python 3.9 (minimum supported version) # - Tusk CLI (for running replay tests) -# - System utilities (curl, postgresql-client) +# - System utilities (curl, postgresql-client, socat, bubblewrap) # # Build this image before running e2e tests: # docker build -t python-e2e-base:latest -f drift/instrumentation/e2e-common/Dockerfile.base . @@ -12,38 +12,40 @@ FROM python:3.9-slim # Install system dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ - curl \ - postgresql-client \ - && rm -rf /var/lib/apt/lists/* + curl \ + postgresql-client \ + socat \ + bubblewrap \ + && rm -rf /var/lib/apt/lists/* # Install Tusk CLI # The CLI is downloaded from GitHub releases (tar.gz archives) ARG TUSK_CLI_VERSION=latest RUN set -ex && \ - if [ "$TUSK_CLI_VERSION" = "latest" ]; then \ - # Get the latest version tag - VERSION=$(curl -s https://api.github.com/repos/Use-Tusk/tusk-drift-cli/releases/latest | grep '"tag_name"' | cut -d '"' -f 4); \ - else \ - VERSION="${TUSK_CLI_VERSION}"; \ - fi && \ - # Remove 'v' prefix if present for the filename - VERSION_NUM=$(echo "$VERSION" | sed 's/^v//') && \ - # Detect architecture (x86_64 or arm64) - ARCH=$(uname -m) && \ - case "$ARCH" in \ - x86_64) ARCH_NAME="x86_64" ;; \ - aarch64|arm64) ARCH_NAME="arm64" ;; \ - *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \ - esac && \ - # Construct download URL (archives are named like tusk-drift-cli_0.1.35_Linux_x86_64.tar.gz) - DOWNLOAD_URL="https://github.com/Use-Tusk/tusk-drift-cli/releases/download/${VERSION}/tusk-drift-cli_${VERSION_NUM}_Linux_${ARCH_NAME}.tar.gz" && \ - echo "Downloading Tusk CLI from: $DOWNLOAD_URL" && \ - curl -fsSL "$DOWNLOAD_URL" -o /tmp/tusk.tar.gz && \ - tar -xzf /tmp/tusk.tar.gz -C /tmp && \ - mv /tmp/tusk /usr/local/bin/tusk && \ - chmod +x /usr/local/bin/tusk && \ - rm -rf /tmp/tusk.tar.gz /tmp/LICENSE /tmp/README.md && \ - tusk --version + if [ "$TUSK_CLI_VERSION" = "latest" ]; then \ + # Get the latest version tag + VERSION=$(curl -s https://api.github.com/repos/Use-Tusk/tusk-drift-cli/releases/latest | grep '"tag_name"' | cut -d '"' -f 4); \ + else \ + VERSION="${TUSK_CLI_VERSION}"; \ + fi && \ + # Remove 'v' prefix if present for the filename + VERSION_NUM=$(echo "$VERSION" | sed 's/^v//') && \ + # Detect architecture (x86_64 or arm64) + ARCH=$(uname -m) && \ + case "$ARCH" in \ + x86_64) ARCH_NAME="x86_64" ;; \ + aarch64|arm64) ARCH_NAME="arm64" ;; \ + *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \ + esac && \ + # Construct download URL (archives are named like tusk-drift-cli_0.1.35_Linux_x86_64.tar.gz) + DOWNLOAD_URL="https://github.com/Use-Tusk/tusk-drift-cli/releases/download/${VERSION}/tusk-drift-cli_${VERSION_NUM}_Linux_${ARCH_NAME}.tar.gz" && \ + echo "Downloading Tusk CLI from: $DOWNLOAD_URL" && \ + curl -fsSL "$DOWNLOAD_URL" -o /tmp/tusk.tar.gz && \ + tar -xzf /tmp/tusk.tar.gz -C /tmp && \ + mv /tmp/tusk /usr/local/bin/tusk && \ + chmod +x /usr/local/bin/tusk && \ + rm -rf /tmp/tusk.tar.gz /tmp/LICENSE /tmp/README.md && \ + tusk --version # Upgrade pip RUN pip install --upgrade pip diff --git a/drift/instrumentation/fastapi/e2e-tests/.tusk/config.yaml b/drift/instrumentation/fastapi/e2e-tests/.tusk/config.yaml index d83870c..f0df935 100644 --- a/drift/instrumentation/fastapi/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/fastapi/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/fastapi/e2e-tests/docker-compose.yml b/drift/instrumentation/fastapi/e2e-tests/docker-compose.yml index c241141..cf2e18c 100644 --- a/drift/instrumentation/fastapi/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/fastapi/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/fastapi/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/fastapi/e2e-tests/requirements.txt b/drift/instrumentation/fastapi/e2e-tests/requirements.txt index 25ca34f..47e8b46 100644 --- a/drift/instrumentation/fastapi/e2e-tests/requirements.txt +++ b/drift/instrumentation/fastapi/e2e-tests/requirements.txt @@ -2,5 +2,6 @@ fastapi>=0.115.0 uvicorn>=0.30.0 requests>=2.32.5 -httpx>=0.27.0 +# Strict replay sandbox routes outbound HTTP through a SOCKS proxy. +httpx[socks]>=0.27.0 diff --git a/drift/instrumentation/flask/e2e-tests/.tusk/config.yaml b/drift/instrumentation/flask/e2e-tests/.tusk/config.yaml index 817477d..78b1271 100644 --- a/drift/instrumentation/flask/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/flask/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/flask/e2e-tests/docker-compose.yml b/drift/instrumentation/flask/e2e-tests/docker-compose.yml index f42b4be..8c73754 100644 --- a/drift/instrumentation/flask/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/flask/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/flask/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/grpc/e2e-tests/.tusk/config.yaml b/drift/instrumentation/grpc/e2e-tests/.tusk/config.yaml index cd9e2bb..05100a8 100644 --- a/drift/instrumentation/grpc/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/grpc/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/grpc/e2e-tests/docker-compose.yml b/drift/instrumentation/grpc/e2e-tests/docker-compose.yml index 6372545..c0d45a7 100644 --- a/drift/instrumentation/grpc/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/grpc/e2e-tests/docker-compose.yml @@ -5,6 +5,11 @@ services: dockerfile: drift/instrumentation/grpc/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/grpc/e2e-tests/src/greeter_pb2_grpc.py b/drift/instrumentation/grpc/e2e-tests/src/greeter_pb2_grpc.py index fa28693..2d32d7e 100644 --- a/drift/instrumentation/grpc/e2e-tests/src/greeter_pb2_grpc.py +++ b/drift/instrumentation/grpc/e2e-tests/src/greeter_pb2_grpc.py @@ -5,7 +5,7 @@ import greeter_pb2 as greeter__pb2 -GRPC_GENERATED_VERSION = '1.76.0' +GRPC_GENERATED_VERSION = '1.78.0' GRPC_VERSION = grpc.__version__ _version_not_supported = False diff --git a/drift/instrumentation/httpx/e2e-tests/.tusk/config.yaml b/drift/instrumentation/httpx/e2e-tests/.tusk/config.yaml index ed91a49..09d36d6 100644 --- a/drift/instrumentation/httpx/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/httpx/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/httpx/e2e-tests/docker-compose.yml b/drift/instrumentation/httpx/e2e-tests/docker-compose.yml index 7db225a..ae57669 100644 --- a/drift/instrumentation/httpx/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/httpx/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/httpx/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/httpx/e2e-tests/requirements.txt b/drift/instrumentation/httpx/e2e-tests/requirements.txt index 9d4518d..8e48040 100644 --- a/drift/instrumentation/httpx/e2e-tests/requirements.txt +++ b/drift/instrumentation/httpx/e2e-tests/requirements.txt @@ -1,4 +1,5 @@ -e /sdk Flask>=3.1.2 -httpx>=0.28.1 +# Strict replay sandbox routes outbound HTTP through a SOCKS proxy. +httpx[socks]>=0.28.1 requests>=2.32.5 diff --git a/drift/instrumentation/psycopg/e2e-tests/.tusk/config.yaml b/drift/instrumentation/psycopg/e2e-tests/.tusk/config.yaml index 3c952d8..d9d8ffa 100644 --- a/drift/instrumentation/psycopg/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/psycopg/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/psycopg/e2e-tests/docker-compose.yml b/drift/instrumentation/psycopg/e2e-tests/docker-compose.yml index 3af56b1..34e6e0a 100644 --- a/drift/instrumentation/psycopg/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/psycopg/e2e-tests/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/instrumentation/psycopg/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/instrumentation/psycopg2/e2e-tests/.tusk/config.yaml b/drift/instrumentation/psycopg2/e2e-tests/.tusk/config.yaml index 1218f96..4e01e23 100644 --- a/drift/instrumentation/psycopg2/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/psycopg2/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/psycopg2/e2e-tests/docker-compose.yml b/drift/instrumentation/psycopg2/e2e-tests/docker-compose.yml index 08cf0b4..608fa98 100644 --- a/drift/instrumentation/psycopg2/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/psycopg2/e2e-tests/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/instrumentation/psycopg2/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/instrumentation/redis/e2e-tests/.tusk/config.yaml b/drift/instrumentation/redis/e2e-tests/.tusk/config.yaml index e86c376..588333a 100644 --- a/drift/instrumentation/redis/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/redis/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/redis/e2e-tests/docker-compose.yml b/drift/instrumentation/redis/e2e-tests/docker-compose.yml index 5d4c39f..84b269c 100644 --- a/drift/instrumentation/redis/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/redis/e2e-tests/docker-compose.yml @@ -13,6 +13,11 @@ services: dockerfile: drift/instrumentation/redis/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: redis: condition: service_healthy diff --git a/drift/instrumentation/requests/e2e-tests/.tusk/config.yaml b/drift/instrumentation/requests/e2e-tests/.tusk/config.yaml index 959280c..6edaa48 100644 --- a/drift/instrumentation/requests/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/requests/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/requests/e2e-tests/docker-compose.yml b/drift/instrumentation/requests/e2e-tests/docker-compose.yml index f1c1591..997da3a 100644 --- a/drift/instrumentation/requests/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/requests/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/requests/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/sqlalchemy/e2e-tests/.tusk/config.yaml b/drift/instrumentation/sqlalchemy/e2e-tests/.tusk/config.yaml index 1f10182..e8bb9d0 100644 --- a/drift/instrumentation/sqlalchemy/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/sqlalchemy/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/sqlalchemy/e2e-tests/docker-compose.yml b/drift/instrumentation/sqlalchemy/e2e-tests/docker-compose.yml index ce99b9b..6a29a0c 100644 --- a/drift/instrumentation/sqlalchemy/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/sqlalchemy/e2e-tests/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/instrumentation/sqlalchemy/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/instrumentation/sqlalchemy/e2e-tests/run.sh b/drift/instrumentation/sqlalchemy/e2e-tests/run.sh old mode 100644 new mode 100755 diff --git a/drift/instrumentation/urllib/e2e-tests/.tusk/config.yaml b/drift/instrumentation/urllib/e2e-tests/.tusk/config.yaml index 41294f6..ee93b43 100644 --- a/drift/instrumentation/urllib/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/urllib/e2e-tests/.tusk/config.yaml @@ -25,3 +25,5 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/urllib/e2e-tests/docker-compose.yml b/drift/instrumentation/urllib/e2e-tests/docker-compose.yml index 32f1585..4beb9b9 100644 --- a/drift/instrumentation/urllib/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/urllib/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/urllib/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/instrumentation/urllib3/e2e-tests/.tusk/config.yaml b/drift/instrumentation/urllib3/e2e-tests/.tusk/config.yaml index 9f66127..a0fbaae 100644 --- a/drift/instrumentation/urllib3/e2e-tests/.tusk/config.yaml +++ b/drift/instrumentation/urllib3/e2e-tests/.tusk/config.yaml @@ -25,4 +25,6 @@ recording: replay: enable_telemetry: false + sandbox: + mode: strict diff --git a/drift/instrumentation/urllib3/e2e-tests/docker-compose.yml b/drift/instrumentation/urllib3/e2e-tests/docker-compose.yml index 40cdfdf..10b39a7 100644 --- a/drift/instrumentation/urllib3/e2e-tests/docker-compose.yml +++ b/drift/instrumentation/urllib3/e2e-tests/docker-compose.yml @@ -14,6 +14,11 @@ services: dockerfile: drift/instrumentation/urllib3/e2e-tests/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined environment: - PORT=8000 - TUSK_ANALYTICS_DISABLED=1 diff --git a/drift/stack-tests/django-postgres/.tusk/config.yaml b/drift/stack-tests/django-postgres/.tusk/config.yaml index efcd04c..28ba50a 100644 --- a/drift/stack-tests/django-postgres/.tusk/config.yaml +++ b/drift/stack-tests/django-postgres/.tusk/config.yaml @@ -19,3 +19,7 @@ recording: sampling_rate: 1.0 export_spans: false exclude_paths: [] + +replay: + sandbox: + mode: strict diff --git a/drift/stack-tests/django-postgres/docker-compose.yml b/drift/stack-tests/django-postgres/docker-compose.yml index b51fd7f..c20e94f 100644 --- a/drift/stack-tests/django-postgres/docker-compose.yml +++ b/drift/stack-tests/django-postgres/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/stack-tests/django-postgres/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/stack-tests/django-redis/.tusk/config.yaml b/drift/stack-tests/django-redis/.tusk/config.yaml index 2fef147..4f6b316 100644 --- a/drift/stack-tests/django-redis/.tusk/config.yaml +++ b/drift/stack-tests/django-redis/.tusk/config.yaml @@ -22,3 +22,7 @@ recording: sampling_rate: 1.0 export_spans: false exclude_paths: [] + +replay: + sandbox: + mode: strict diff --git a/drift/stack-tests/django-redis/docker-compose.yml b/drift/stack-tests/django-redis/docker-compose.yml index e5ca482..1570b8a 100644 --- a/drift/stack-tests/django-redis/docker-compose.yml +++ b/drift/stack-tests/django-redis/docker-compose.yml @@ -13,6 +13,11 @@ services: dockerfile: drift/stack-tests/django-redis/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: redis: condition: service_healthy diff --git a/drift/stack-tests/fastapi-postgres/.tusk/config.yaml b/drift/stack-tests/fastapi-postgres/.tusk/config.yaml index f6f4023..2ad9679 100644 --- a/drift/stack-tests/fastapi-postgres/.tusk/config.yaml +++ b/drift/stack-tests/fastapi-postgres/.tusk/config.yaml @@ -19,3 +19,7 @@ recording: sampling_rate: 1.0 export_spans: false exclude_paths: [] + +replay: + sandbox: + mode: strict diff --git a/drift/stack-tests/fastapi-postgres/docker-compose.yml b/drift/stack-tests/fastapi-postgres/docker-compose.yml index 1fcdb20..3497e5e 100644 --- a/drift/stack-tests/fastapi-postgres/docker-compose.yml +++ b/drift/stack-tests/fastapi-postgres/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/stack-tests/fastapi-postgres/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/stack-tests/fastapi-sqlalchemy/.tusk/config.yaml b/drift/stack-tests/fastapi-sqlalchemy/.tusk/config.yaml index 9d81eea..746f3ea 100644 --- a/drift/stack-tests/fastapi-sqlalchemy/.tusk/config.yaml +++ b/drift/stack-tests/fastapi-sqlalchemy/.tusk/config.yaml @@ -19,3 +19,7 @@ recording: sampling_rate: 1.0 export_spans: false exclude_paths: [] + +replay: + sandbox: + mode: strict diff --git a/drift/stack-tests/fastapi-sqlalchemy/docker-compose.yml b/drift/stack-tests/fastapi-sqlalchemy/docker-compose.yml index c3aa3c8..25b8a82 100644 --- a/drift/stack-tests/fastapi-sqlalchemy/docker-compose.yml +++ b/drift/stack-tests/fastapi-sqlalchemy/docker-compose.yml @@ -17,6 +17,11 @@ services: dockerfile: drift/stack-tests/fastapi-sqlalchemy/Dockerfile args: - TUSK_CLI_VERSION=${TUSK_CLI_VERSION:-latest} + cap_add: + - SYS_ADMIN + security_opt: + - seccomp=unconfined + - apparmor=unconfined depends_on: postgres: condition: service_healthy diff --git a/drift/stack-tests/fastapi-sqlalchemy/run.sh b/drift/stack-tests/fastapi-sqlalchemy/run.sh old mode 100644 new mode 100755 From a7945361886fa0642ddb38336164477eb8c24543 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Wed, 18 Mar 2026 18:06:33 -0700 Subject: [PATCH 2/4] Run e2e workflow with service logs printed --- .github/workflows/e2e.yml | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index b5048a1..146180e 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -108,6 +108,29 @@ jobs: chmod +x ./drift/instrumentation/${{ matrix.library }}/e2e-tests/run.sh cd ./drift/instrumentation/${{ matrix.library }}/e2e-tests && ./run.sh 8000 + - name: Print replay logs for ${{ matrix.library }} + if: always() + run: | + shopt -s nullglob + logs=(./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs/*) + if [ ${#logs[@]} -eq 0 ]; then + echo "No replay logs found" + exit 0 + fi + + for f in "${logs[@]}"; do + echo "=== $f ===" + cat "$f" + done + + - name: Upload replay logs for ${{ matrix.library }} + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-${{ matrix.library }}-replay-logs + path: ./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs/* + if-no-files-found: ignore + - name: Cleanup Docker resources if: always() run: | @@ -186,6 +209,29 @@ jobs: chmod +x ./drift/stack-tests/${{ matrix.test }}/run.sh cd ./drift/stack-tests/${{ matrix.test }} && ./run.sh 8000 + - name: Print replay logs for ${{ matrix.test }} + if: always() + run: | + shopt -s nullglob + logs=(./drift/stack-tests/${{ matrix.test }}/.tusk/logs/*) + if [ ${#logs[@]} -eq 0 ]; then + echo "No replay logs found" + exit 0 + fi + + for f in "${logs[@]}"; do + echo "=== $f ===" + cat "$f" + done + + - name: Upload replay logs for ${{ matrix.test }} + if: always() + uses: actions/upload-artifact@v4 + with: + name: stack-${{ matrix.test }}-replay-logs + path: ./drift/stack-tests/${{ matrix.test }}/.tusk/logs/* + if-no-files-found: ignore + - name: Cleanup Docker resources if: always() run: | @@ -257,6 +303,29 @@ jobs: chmod +x ./drift/instrumentation/requests/e2e-tests/run.sh cd ./drift/instrumentation/requests/e2e-tests && ./run.sh 8000 + - name: Print replay logs for requests smoke test + if: always() + run: | + shopt -s nullglob + logs=(./drift/instrumentation/requests/e2e-tests/.tusk/logs/*) + if [ ${#logs[@]} -eq 0 ]; then + echo "No replay logs found" + exit 0 + fi + + for f in "${logs[@]}"; do + echo "=== $f ===" + cat "$f" + done + + - name: Upload replay logs for requests smoke test + if: always() + uses: actions/upload-artifact@v4 + with: + name: requests-smoke-replay-logs + path: ./drift/instrumentation/requests/e2e-tests/.tusk/logs/* + if-no-files-found: ignore + - name: Cleanup Docker resources if: always() run: | From f27b3bdd7fcb1732aaa9e78368eaf1b7fb393cb4 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Wed, 18 Mar 2026 18:14:31 -0700 Subject: [PATCH 3/4] Fix --- .github/workflows/e2e.yml | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 146180e..8dfd5f8 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -111,8 +111,17 @@ jobs: - name: Print replay logs for ${{ matrix.library }} if: always() run: | + log_dir=./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs + if ! sudo test -d "$log_dir"; then + echo "No replay log directory found" + exit 0 + fi + + sudo chmod -R a+rX "$log_dir" || true + sudo chown -R "$(id -u):$(id -g)" "$log_dir" || true + shopt -s nullglob - logs=(./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs/*) + logs=("$log_dir"/*) if [ ${#logs[@]} -eq 0 ]; then echo "No replay logs found" exit 0 @@ -128,7 +137,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: e2e-${{ matrix.library }}-replay-logs - path: ./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs/* + path: ./drift/instrumentation/${{ matrix.library }}/e2e-tests/.tusk/logs if-no-files-found: ignore - name: Cleanup Docker resources @@ -212,8 +221,17 @@ jobs: - name: Print replay logs for ${{ matrix.test }} if: always() run: | + log_dir=./drift/stack-tests/${{ matrix.test }}/.tusk/logs + if ! sudo test -d "$log_dir"; then + echo "No replay log directory found" + exit 0 + fi + + sudo chmod -R a+rX "$log_dir" || true + sudo chown -R "$(id -u):$(id -g)" "$log_dir" || true + shopt -s nullglob - logs=(./drift/stack-tests/${{ matrix.test }}/.tusk/logs/*) + logs=("$log_dir"/*) if [ ${#logs[@]} -eq 0 ]; then echo "No replay logs found" exit 0 @@ -229,7 +247,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: stack-${{ matrix.test }}-replay-logs - path: ./drift/stack-tests/${{ matrix.test }}/.tusk/logs/* + path: ./drift/stack-tests/${{ matrix.test }}/.tusk/logs if-no-files-found: ignore - name: Cleanup Docker resources @@ -306,8 +324,17 @@ jobs: - name: Print replay logs for requests smoke test if: always() run: | + log_dir=./drift/instrumentation/requests/e2e-tests/.tusk/logs + if ! sudo test -d "$log_dir"; then + echo "No replay log directory found" + exit 0 + fi + + sudo chmod -R a+rX "$log_dir" || true + sudo chown -R "$(id -u):$(id -g)" "$log_dir" || true + shopt -s nullglob - logs=(./drift/instrumentation/requests/e2e-tests/.tusk/logs/*) + logs=("$log_dir"/*) if [ ${#logs[@]} -eq 0 ]; then echo "No replay logs found" exit 0 @@ -323,7 +350,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: requests-smoke-replay-logs - path: ./drift/instrumentation/requests/e2e-tests/.tusk/logs/* + path: ./drift/instrumentation/requests/e2e-tests/.tusk/logs if-no-files-found: ignore - name: Cleanup Docker resources From e8270397c7985a31842521f72a1982e6c100a5c8 Mon Sep 17 00:00:00 2001 From: JY Tan Date: Wed, 18 Mar 2026 22:14:17 -0700 Subject: [PATCH 4/4] Debug --- .../grpc/e2e-tests/src/grpc_server.py | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py b/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py index 6f321c1..c4290d2 100644 --- a/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py +++ b/drift/instrumentation/grpc/e2e-tests/src/grpc_server.py @@ -1,5 +1,7 @@ """gRPC server for e2e tests.""" +import os +import stat import time from concurrent import futures @@ -9,6 +11,70 @@ import grpc +def _log_device_probe(path: str): + """Print detailed device diagnostics for sandbox debugging.""" + try: + info = os.stat(path) + device_kind = "char" if stat.S_ISCHR(info.st_mode) else "other" + device_id = "-" + if stat.S_ISCHR(info.st_mode): + device_id = f"{os.major(info.st_rdev)}:{os.minor(info.st_rdev)}" + print( + f"[grpc probe] {path}: mode={oct(stat.S_IMODE(info.st_mode))} " + f"kind={device_kind} rdev={device_id} " + f"readable={os.access(path, os.R_OK)} writable={os.access(path, os.W_OK)}", + flush=True, + ) + except OSError as exc: + print( + f"[grpc probe] stat({path}) failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + return + + try: + fd = os.open(path, os.O_RDONLY) + try: + data = os.read(fd, 1) + print(f"[grpc probe] read({path}) ok: bytes={len(data)}", flush=True) + finally: + os.close(fd) + except OSError as exc: + print( + f"[grpc probe] open/read({path}) failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + + +def _log_startup_probe(): + """Emit diagnostics to pinpoint sandbox/device failures in CI.""" + print( + f"[grpc probe] pid={os.getpid()} uid={os.getuid()} euid={os.geteuid()} cwd={os.getcwd()}", + flush=True, + ) + try: + dev_entries = ", ".join(sorted(os.listdir("/dev"))) + print(f"[grpc probe] /dev entries: {dev_entries}", flush=True) + except OSError as exc: + print( + f"[grpc probe] listdir(/dev) failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + + for device_path in ("/dev/urandom", "/dev/random", "/dev/null"): + _log_device_probe(device_path) + + if hasattr(os, "getrandom"): + try: + sample = os.getrandom(1) + print(f"[grpc probe] getrandom() ok: bytes={len(sample)}", flush=True) + except OSError as exc: + print( + f"[grpc probe] getrandom() failed: errno={exc.errno} strerror={exc.strerror}", + flush=True, + ) + + class GreeterServicer(greeter_pb2_grpc.GreeterServicer): """Implementation of the Greeter service.""" @@ -61,11 +127,19 @@ def Chat(self, request_iterator, context): def serve(port: int = 50051): """Start the gRPC server.""" + print("[grpc probe] before startup probe", flush=True) + _log_startup_probe() + print("[grpc probe] before grpc.server()", flush=True) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) + print("[grpc probe] after grpc.server()", flush=True) greeter_pb2_grpc.add_GreeterServicer_to_server(GreeterServicer(), server) - server.add_insecure_port(f"[::]:{port}") + print("[grpc probe] after add_GreeterServicer_to_server()", flush=True) + bound_port = server.add_insecure_port(f"[::]:{port}") + print(f"[grpc probe] add_insecure_port returned {bound_port}", flush=True) + print("[grpc probe] before server.start()", flush=True) server.start() - print(f"gRPC server started on port {port}") + print("[grpc probe] after server.start()", flush=True) + print(f"gRPC server started on port {port}", flush=True) return server