163 lines
6.7 KiB
Bash
Executable File
163 lines
6.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# test_isolation.sh — тестирует namespace изоляцию:
|
|
# Пользователь A не видит и не может изменить функции пользователя B.
|
|
# LIST каждого пользователя возвращает только его функции.
|
|
set -uo pipefail
|
|
|
|
ROOT_DIR=$(cd "$(dirname "$0")" && pwd)
|
|
source "${ROOT_DIR}/lib.sh"
|
|
|
|
NS_CLEANUP_SCRIPT="${ROOT_DIR}/cleanup_test_namespaces.sh"
|
|
RUN_ID=$(mk_run_id)
|
|
ALICE="alice-${RUN_ID}@test.local"
|
|
BOB="bob-${RUN_ID}@test.local"
|
|
|
|
cleanup() {
|
|
if [ -x "$NS_CLEANUP_SCRIPT" ]; then
|
|
KUBECTL_DIRECT=1 "$NS_CLEANUP_SCRIPT" "$ALICE" "$BOB" >/dev/null 2>&1 || true
|
|
fi
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
echo ""
|
|
echo "========================================"
|
|
echo " test_isolation.sh run=$RUN_ID"
|
|
echo "========================================"
|
|
|
|
JS_CODE='module.exports = async function() { return { status: 200, body: "ok" }; }'
|
|
|
|
# ── Alice создаёт функцию ─────────────────────────────────────────────────────
|
|
|
|
echo ""
|
|
echo ">>> Alice создаёт функцию"
|
|
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions" \
|
|
-H "X-Auth-Token: ${ALICE}" -H "Content-Type: application/json" \
|
|
-d "{\"name\":\"alice-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}")
|
|
check_http "$(echo "$R" | tail -1)" "201" "Alice CREATE alice-fn → 201"
|
|
|
|
# ── Bob не может получить функцию Alice ──────────────────────────────────────
|
|
|
|
echo ""
|
|
echo ">>> Bob GET alice-fn → 404"
|
|
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/alice-fn" \
|
|
-H "X-Auth-Token: ${BOB}")
|
|
check_http "$(echo "$R" | tail -1)" "404" "Bob GET alice-fn → 404"
|
|
|
|
echo ""
|
|
echo ">>> Bob DELETE alice-fn → 404"
|
|
R=$(curl -s -w "\n%{http_code}" -X DELETE "${BASE}/functions/alice-fn" \
|
|
-H "X-Auth-Token: ${BOB}")
|
|
check_http "$(echo "$R" | tail -1)" "404" "Bob DELETE alice-fn → 404"
|
|
|
|
echo ""
|
|
echo ">>> Bob PUT alice-fn/code → 404"
|
|
R=$(curl -s -w "\n%{http_code}" -X PUT "${BASE}/functions/alice-fn/code" \
|
|
-H "X-Auth-Token: ${BOB}" -H "Content-Type: application/json" \
|
|
-d '{"code":"module.exports = async () => ({ body: \"hacked\" });"}')
|
|
check_http "$(echo "$R" | tail -1)" "404" "Bob PUT alice-fn/code → 404"
|
|
|
|
echo ""
|
|
echo ">>> Bob INVOKE alice-fn → 404"
|
|
R=$(curl -s -w "\n%{http_code}" -X POST "${BASE}/functions/alice-fn/invoke" \
|
|
-H "X-Auth-Token: ${BOB}" -H "Content-Type: application/json" -d '{}')
|
|
check_http "$(echo "$R" | tail -1)" "404" "Bob INVOKE alice-fn → 404"
|
|
|
|
# ── Alice убеждается что её функция цела ────────────────────────────────────
|
|
|
|
echo ""
|
|
echo ">>> Alice GET alice-fn → 200 (не повреждена)"
|
|
R=$(curl -s -w "\n%{http_code}" "${BASE}/functions/alice-fn" \
|
|
-H "X-Auth-Token: ${ALICE}")
|
|
check_http "$(echo "$R" | tail -1)" "200" "Alice GET alice-fn → 200"
|
|
|
|
# ── LIST изоляция ────────────────────────────────────────────────────────────
|
|
|
|
echo ""
|
|
echo ">>> LIST изоляция: Alice и Bob видят только свои функции"
|
|
|
|
# Bob создаёт свою функцию
|
|
curl -s -X POST "${BASE}/functions" \
|
|
-H "X-Auth-Token: ${BOB}" -H "Content-Type: application/json" \
|
|
-d "{\"name\":\"bob-fn\",\"language\":\"nodejs\",\"code\":$(printf '%s' "$JS_CODE" | json_escape)}" > /dev/null
|
|
|
|
sleep 1
|
|
|
|
ALICE_LIST=$(curl -s "${BASE}/functions" -H "X-Auth-Token: ${ALICE}")
|
|
BOB_LIST=$(curl -s "${BASE}/functions" -H "X-Auth-Token: ${BOB}")
|
|
|
|
# Alice видит alice-fn но не bob-fn
|
|
ALICE_COUNT=$(json_len "$ALICE_LIST")
|
|
ALICE_HAS_OWN=$(printf '%s' "$ALICE_LIST" | python3 -c "
|
|
import json, sys
|
|
try:
|
|
fns = json.load(sys.stdin)
|
|
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 'alice-fn'))
|
|
except:
|
|
print(0)" 2>/dev/null)
|
|
ALICE_HAS_BOB=$(printf '%s' "$ALICE_LIST" | python3 -c "
|
|
import json, sys
|
|
try:
|
|
fns = json.load(sys.stdin)
|
|
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 'bob-fn'))
|
|
except:
|
|
print(0)" 2>/dev/null)
|
|
|
|
[ "${ALICE_HAS_OWN:-0}" -ge 1 ] && pass "Alice LIST содержит alice-fn" || fail "Alice LIST не содержит alice-fn (count=$ALICE_COUNT)"
|
|
[ "${ALICE_HAS_BOB:-0}" -eq 0 ] && pass "Alice LIST не содержит bob-fn" || fail "Alice LIST содержит bob-fn — УТЕЧКА ДАННЫХ!"
|
|
|
|
# Bob видит bob-fn но не alice-fn
|
|
BOB_HAS_OWN=$(printf '%s' "$BOB_LIST" | python3 -c "
|
|
import json, sys
|
|
try:
|
|
fns = json.load(sys.stdin)
|
|
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 'bob-fn'))
|
|
except:
|
|
print(0)" 2>/dev/null)
|
|
BOB_HAS_ALICE=$(printf '%s' "$BOB_LIST" | python3 -c "
|
|
import json, sys
|
|
try:
|
|
fns = json.load(sys.stdin)
|
|
print(sum(1 for f in fns if f.get('metadata',{}).get('name','') == 'alice-fn'))
|
|
except:
|
|
print(0)" 2>/dev/null)
|
|
|
|
[ "${BOB_HAS_OWN:-0}" -ge 1 ] && pass "Bob LIST содержит bob-fn" || fail "Bob LIST не содержит bob-fn"
|
|
[ "${BOB_HAS_ALICE:-0}" -eq 0 ] && pass "Bob LIST не содержит alice-fn" || fail "Bob LIST содержит alice-fn — УТЕЧКА ДАННЫХ!"
|
|
|
|
# ── Route изоляция ───────────────────────────────────────────────────────────
|
|
|
|
echo ""
|
|
echo ">>> Route изоляция: одинаковое имя → разные routes"
|
|
ROUTE_A=$(printf '%s' "$ALICE_LIST" | python3 -c "
|
|
import json, sys
|
|
try:
|
|
fns = json.load(sys.stdin)
|
|
for f in fns:
|
|
if f.get('metadata',{}).get('name','') == 'alice-fn':
|
|
print(f.get('spec',{}).get('relativeurl',''))
|
|
break
|
|
except:
|
|
print('')" 2>/dev/null)
|
|
|
|
ROUTE_B=$(printf '%s' "$BOB_LIST" | python3 -c "
|
|
import json, sys
|
|
try:
|
|
fns = json.load(sys.stdin)
|
|
for f in fns:
|
|
if f.get('metadata',{}).get('name','') == 'bob-fn':
|
|
print(f.get('spec',{}).get('relativeurl',''))
|
|
break
|
|
except:
|
|
print('')" 2>/dev/null)
|
|
|
|
# Проверяем через GET (возвращает route)
|
|
ALICE_GET=$(curl -s "${BASE}/functions/alice-fn" -H "X-Auth-Token: ${ALICE}")
|
|
BOB_GET=$(curl -s "${BASE}/functions/bob-fn" -H "X-Auth-Token: ${BOB}")
|
|
ROUTE_A=$(json_field "$ALICE_GET" route)
|
|
ROUTE_B=$(json_field "$BOB_GET" route)
|
|
[ "$ROUTE_A" != "$ROUTE_B" ] && [ -n "$ROUTE_A" ] && [ -n "$ROUTE_B" ] \
|
|
&& pass "Route изоляция: $ROUTE_A ≠ $ROUTE_B" \
|
|
|| fail "Route коллизия: alice=$ROUTE_A bob=$ROUTE_B"
|
|
|
|
print_summary
|