|
| 1 | +#!/usr/bin/env bash |
| 2 | +set -euo pipefail |
| 3 | + |
| 4 | +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" |
| 5 | +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" |
| 6 | +TEST_ROOT=$(mktemp -d) |
| 7 | +trap 'rm -rf "$TEST_ROOT"' EXIT |
| 8 | + |
| 9 | +FAKE_BIN="$TEST_ROOT/bin" |
| 10 | +UUIDGEN_LOG="$TEST_ROOT/uuidgen.log" |
| 11 | +CURL_PAYLOAD_FILE="$TEST_ROOT/curl-payload.json" |
| 12 | +CURL_REDIRECT_POLICY_LOG="$TEST_ROOT/curl-redirect-policy.log" |
| 13 | +mkdir -p "$FAKE_BIN" |
| 14 | +: > "$UUIDGEN_LOG" |
| 15 | +: > "$CURL_REDIRECT_POLICY_LOG" |
| 16 | + |
| 17 | +cat > "$FAKE_BIN/uuidgen" <<'EOF' |
| 18 | +#!/usr/bin/env bash |
| 19 | +if [[ "${UUIDGEN_SHOULD_FAIL:-false}" == "true" ]]; then |
| 20 | + exit 1 |
| 21 | +fi |
| 22 | +printf 'called\n' >> "$UUIDGEN_LOG" |
| 23 | +printf 'generated-install-id\n' |
| 24 | +EOF |
| 25 | + |
| 26 | +cat > "$FAKE_BIN/curl" <<'EOF' |
| 27 | +#!/usr/bin/env bash |
| 28 | +follow_redirects=false |
| 29 | +proto_redir="" |
| 30 | +payload="" |
| 31 | +method="GET" |
| 32 | +
|
| 33 | +while (($# > 0)); do |
| 34 | + case "$1" in |
| 35 | + -L|--location) |
| 36 | + follow_redirects=true |
| 37 | + ;; |
| 38 | + --proto-redir) |
| 39 | + shift |
| 40 | + proto_redir="$1" |
| 41 | + ;; |
| 42 | + -d|--data) |
| 43 | + shift |
| 44 | + payload="$1" |
| 45 | + method="POST" |
| 46 | + ;; |
| 47 | + -X|--request) |
| 48 | + shift |
| 49 | + method="$1" |
| 50 | + ;; |
| 51 | + esac |
| 52 | + shift |
| 53 | +done |
| 54 | +
|
| 55 | +if [[ -z "$payload" ]]; then |
| 56 | + exit 1 |
| 57 | +fi |
| 58 | +printf '%s\n' "$payload" > "$CURL_PAYLOAD_FILE" |
| 59 | +
|
| 60 | +if [[ "${CURL_REDIRECT_STATUS:-}" =~ ^30(7|8)$ && "${CURL_REDIRECT_URL:-}" == http://* ]]; then |
| 61 | + printf '%s|%s|%s|%s\n' "$CURL_REDIRECT_STATUS" "$follow_redirects" "$proto_redir" "$method" >> "$CURL_REDIRECT_POLICY_LOG" |
| 62 | + if [[ "$follow_redirects" == "true" && "$proto_redir" != "=https" ]]; then |
| 63 | + printf 'followed insecure redirect\n' >> "$CURL_REDIRECT_POLICY_LOG" |
| 64 | + fi |
| 65 | + exit 1 |
| 66 | +fi |
| 67 | +EOF |
| 68 | + |
| 69 | +cat > "$FAKE_BIN/yarn" <<'EOF' |
| 70 | +#!/usr/bin/env bash |
| 71 | +exit 0 |
| 72 | +EOF |
| 73 | + |
| 74 | +cat > "$FAKE_BIN/mkdir" <<'EOF' |
| 75 | +#!/usr/bin/env bash |
| 76 | +exit 0 |
| 77 | +EOF |
| 78 | + |
| 79 | +cat > "$FAKE_BIN/supervisord" <<'EOF' |
| 80 | +#!/usr/bin/env bash |
| 81 | +printf '%s\n' "$SOURCEBOT_INSTALL_ID" > "$RESULT_FILE" |
| 82 | +EOF |
| 83 | + |
| 84 | +chmod +x "$FAKE_BIN/uuidgen" "$FAKE_BIN/curl" "$FAKE_BIN/yarn" "$FAKE_BIN/mkdir" "$FAKE_BIN/supervisord" |
| 85 | + |
| 86 | +run_entrypoint() { |
| 87 | + local data_dir="$1" |
| 88 | + local result_file="$2" |
| 89 | + shift 2 |
| 90 | + |
| 91 | + env \ |
| 92 | + PATH="$FAKE_BIN:$PATH" \ |
| 93 | + UUIDGEN_LOG="$UUIDGEN_LOG" \ |
| 94 | + UUIDGEN_SHOULD_FAIL="false" \ |
| 95 | + CURL_PAYLOAD_FILE="$CURL_PAYLOAD_FILE" \ |
| 96 | + CURL_REDIRECT_POLICY_LOG="$CURL_REDIRECT_POLICY_LOG" \ |
| 97 | + CURL_REDIRECT_STATUS="" \ |
| 98 | + CURL_REDIRECT_URL="" \ |
| 99 | + RESULT_FILE="$result_file" \ |
| 100 | + DATA_CACHE_DIR="$data_dir" \ |
| 101 | + DATABASE_URL="postgresql://test" \ |
| 102 | + REDIS_URL="redis://test" \ |
| 103 | + SOURCEBOT_ENCRYPTION_KEY="test-encryption-key" \ |
| 104 | + AUTH_SECRET="test-auth-secret" \ |
| 105 | + AUTH_URL="http://localhost:3000" \ |
| 106 | + SOURCEBOT_TELEMETRY_DISABLED="true" \ |
| 107 | + "$@" \ |
| 108 | + /bin/sh "$REPO_ROOT/entrypoint.sh" >/dev/null |
| 109 | +} |
| 110 | + |
| 111 | +assert_equals() { |
| 112 | + local description="$1" |
| 113 | + local actual="$2" |
| 114 | + local expected="$3" |
| 115 | + |
| 116 | + if [[ "$actual" != "$expected" ]]; then |
| 117 | + echo "FAIL: $description" |
| 118 | + echo "Expected: $expected" |
| 119 | + echo "Actual: $actual" |
| 120 | + exit 1 |
| 121 | + fi |
| 122 | +} |
| 123 | + |
| 124 | +supplied_data="$TEST_ROOT/supplied-data" |
| 125 | +supplied_result="$TEST_ROOT/supplied-result" |
| 126 | +supplied_id=$'supplied"install\\id\nsecond-line' |
| 127 | +mkdir -p "$supplied_data" |
| 128 | +run_entrypoint "$supplied_data" "$supplied_result" SOURCEBOT_INSTALL_ID="$supplied_id" SOURCEBOT_TELEMETRY_DISABLED="false" POSTHOG_PAPIK="test-project-key" CURL_REDIRECT_STATUS="307" CURL_REDIRECT_URL="http://insecure.example/capture/" |
| 129 | +assert_equals "uses the supplied install ID on first boot" "$(<"$supplied_result")" "$supplied_id" |
| 130 | +assert_equals "persists the supplied install ID as valid JSON" "$(jq -r '.install_id' "$supplied_data/.installedv3")" "$supplied_id" |
| 131 | +assert_equals "does not generate an ID when one is supplied" "$(wc -l < "$UUIDGEN_LOG" | tr -d ' ')" "0" |
| 132 | +if ! jq -e --arg expected "$supplied_id" \ |
| 133 | + '.event == "install" and .distinct_id == $expected and .api_key == "test-project-key"' \ |
| 134 | + "$CURL_PAYLOAD_FILE" >/dev/null; then |
| 135 | + echo "FAIL: install telemetry payload did not safely encode the supplied install ID" |
| 136 | + exit 1 |
| 137 | +fi |
| 138 | +assert_equals "blocks an HTTP 307 redirect without changing the POST method" "$(sed -n '1p' "$CURL_REDIRECT_POLICY_LOG")" "307|true|=https|POST" |
| 139 | + |
| 140 | +# Exercise the next-boot read and upgrade telemetry paths with the same escaped ID. |
| 141 | +jq -n --arg install_id "$supplied_id" \ |
| 142 | + '{version: "previous-version", install_id: $install_id}' > "$supplied_data/.installedv3" |
| 143 | +supplied_restart_result="$TEST_ROOT/supplied-restart-result" |
| 144 | +run_entrypoint "$supplied_data" "$supplied_restart_result" SOURCEBOT_INSTALL_ID="conflicting-install-id" SOURCEBOT_TELEMETRY_DISABLED="false" POSTHOG_PAPIK="test-project-key" CURL_REDIRECT_STATUS="308" CURL_REDIRECT_URL="http://insecure.example/capture/" |
| 145 | +assert_equals "reads the escaped install ID on the next boot" "$(<"$supplied_restart_result")" "$supplied_id" |
| 146 | +if ! jq -e --arg expected "$supplied_id" \ |
| 147 | + '.event == "upgrade" and .distinct_id == $expected and .api_key == "test-project-key"' \ |
| 148 | + "$CURL_PAYLOAD_FILE" >/dev/null; then |
| 149 | + echo "FAIL: upgrade telemetry payload did not safely encode the persisted install ID" |
| 150 | + exit 1 |
| 151 | +fi |
| 152 | +assert_equals "blocks an HTTP 308 redirect without changing the POST method" "$(sed -n '2p' "$CURL_REDIRECT_POLICY_LOG")" "308|true|=https|POST" |
| 153 | +assert_equals "never follows an insecure telemetry redirect" "$(wc -l < "$CURL_REDIRECT_POLICY_LOG" | tr -d ' ')" "2" |
| 154 | + |
| 155 | +generated_data="$TEST_ROOT/generated-data" |
| 156 | +generated_result="$TEST_ROOT/generated-result" |
| 157 | +mkdir -p "$generated_data" |
| 158 | +run_entrypoint "$generated_data" "$generated_result" SOURCEBOT_INSTALL_ID="" |
| 159 | +assert_equals "generates an install ID when none is supplied" "$(<"$generated_result")" "generated-install-id" |
| 160 | +assert_equals "persists the generated install ID" "$(jq -r '.install_id' "$generated_data/.installedv3")" "generated-install-id" |
| 161 | +assert_equals "generates exactly one install ID" "$(wc -l < "$UUIDGEN_LOG" | tr -d ' ')" "1" |
| 162 | + |
| 163 | +existing_data="$TEST_ROOT/existing-data" |
| 164 | +existing_result="$TEST_ROOT/existing-result" |
| 165 | +mkdir -p "$existing_data" |
| 166 | +printf '{"version":"existing-version","install_id":"persisted-install-id"}\n' > "$existing_data/.installedv3" |
| 167 | +run_entrypoint "$existing_data" "$existing_result" SOURCEBOT_INSTALL_ID="conflicting-install-id" |
| 168 | +assert_equals "keeps the persisted install ID after first boot" "$(<"$existing_result")" "persisted-install-id" |
| 169 | +assert_equals "does not generate another ID after first boot" "$(wc -l < "$UUIDGEN_LOG" | tr -d ' ')" "1" |
| 170 | + |
| 171 | +failed_data="$TEST_ROOT/failed-data" |
| 172 | +failed_result="$TEST_ROOT/failed-result" |
| 173 | +mkdir -p "$failed_data" |
| 174 | +if run_entrypoint "$failed_data" "$failed_result" SOURCEBOT_INSTALL_ID="" UUIDGEN_SHOULD_FAIL="true"; then |
| 175 | + echo "FAIL: entrypoint succeeded when install ID generation failed" |
| 176 | + exit 1 |
| 177 | +fi |
| 178 | +if [[ -e "$failed_data/.installedv3" ]]; then |
| 179 | + echo "FAIL: entrypoint left an invalid first-run file after install ID generation failed" |
| 180 | + exit 1 |
| 181 | +fi |
| 182 | + |
| 183 | +echo "Entrypoint install ID tests passed." |
0 commit comments