#!/usr/bin/env bash # Warpgate Integration Test — Mock NAS (SFTP server in network namespace) # # Creates a Linux network namespace with a veth pair and runs an SFTP-only # SSH daemon. This lets tests control "network" behavior (down/up/latency) # without affecting the host. # # Topology: # Host namespace nas-sim namespace # veth-wg (10.99.0.1/24) <---> veth-nas (10.99.0.2/24) # └─ sshd (SFTP on :22) # └─ NAS root: $NAS_ROOT set -euo pipefail MOCK_NAS_NS="${MOCK_NAS_NS:-nas-sim}" MOCK_NAS_IP="${MOCK_NAS_IP:-10.99.0.2}" HOST_IP="${HOST_IP:-10.99.0.1}" MOCK_NAS_SSHD_PID="" start_mock_nas() { require_root local sshd_config="$TEST_DIR/sshd_config" local host_key="$TEST_DIR/ssh_host_key" local auth_keys="$TEST_DIR/authorized_keys" # Generate host key for sshd ssh-keygen -t ed25519 -f "$host_key" -N "" -q # Set up authorized_keys from the test key cp "$TEST_SSH_PUBKEY" "$auth_keys" chmod 600 "$auth_keys" # Create network namespace ip netns add "$MOCK_NAS_NS" 2>/dev/null || true # Create veth pair ip link add veth-wg type veth peer name veth-nas 2>/dev/null || true # Move one end into the namespace ip link set veth-nas netns "$MOCK_NAS_NS" # Configure host side ip addr add "$HOST_IP/24" dev veth-wg 2>/dev/null || true ip link set veth-wg up # Configure namespace side ip netns exec "$MOCK_NAS_NS" ip addr add "$MOCK_NAS_IP/24" dev veth-nas 2>/dev/null || true ip netns exec "$MOCK_NAS_NS" ip link set veth-nas up ip netns exec "$MOCK_NAS_NS" ip link set lo up # Write sshd config (SFTP-only, no password auth, restricted to NAS_ROOT) cat > "$sshd_config" < /dev/tcp/$MOCK_NAS_IP/22" 2>/dev/null; then break fi sleep 0.5 done export MOCK_NAS_SSHD_PID } stop_mock_nas() { # Kill sshd if [[ -n "${MOCK_NAS_SSHD_PID:-}" ]] && kill -0 "$MOCK_NAS_SSHD_PID" 2>/dev/null; then kill "$MOCK_NAS_SSHD_PID" 2>/dev/null || true wait "$MOCK_NAS_SSHD_PID" 2>/dev/null || true fi # Also kill by PID file if [[ -f "${TEST_DIR:-}/sshd.pid" ]]; then local pid pid=$(cat "$TEST_DIR/sshd.pid" 2>/dev/null || true) if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null; then kill "$pid" 2>/dev/null || true fi fi # Clean up veth pair (deleting one end removes both) ip link del veth-wg 2>/dev/null || true # Delete network namespace ip netns del "$MOCK_NAS_NS" 2>/dev/null || true MOCK_NAS_SSHD_PID="" } # Verify mock NAS is reachable via SFTP verify_mock_nas() { sftp -i "$TEST_SSH_KEY" \ -o StrictHostKeyChecking=no \ -o UserKnownHostsFile=/dev/null \ -o ConnectTimeout=5 \ -P 22 \ "root@$MOCK_NAS_IP" <<< "ls" > /dev/null 2>&1 } # Create a file directly on the mock NAS filesystem nas_create_file() { local path="$1" local size_kb="${2:-1}" local full_path="$NAS_ROOT/$path" mkdir -p "$(dirname "$full_path")" dd if=/dev/urandom of="$full_path" bs=1K count="$size_kb" 2>/dev/null } # Create a file with specific content on the mock NAS nas_create_file_content() { local path="$1" local content="$2" local full_path="$NAS_ROOT/$path" mkdir -p "$(dirname "$full_path")" echo -n "$content" > "$full_path" } # Read a file from the mock NAS nas_read_file() { local path="$1" cat "$NAS_ROOT/$path" } # Check if a file exists on the mock NAS nas_file_exists() { local path="$1" [[ -f "$NAS_ROOT/$path" ]] } # Get file checksum on the mock NAS nas_file_checksum() { local path="$1" md5sum "$NAS_ROOT/$path" | awk '{print $1}' }