旧值(jianf 的 user key,1759666 起在历史里)已从库里删除,实测 `/auth/me` → **401**,即暴露在历史中的那串现在无效。新值只存在 /root/gotmp/verify-l2-token.txt(600),脚本 6/6 通过。 - 只删当前行**不等于**作废:git 历史里的密钥必须靠轮换才能失效。 - 轮换前先核对过使用面:全仓库只有这一处,/root 下的脚本与运行进程环境里都没有。 - 生产库里临时建的留档表已 DROP,那行旧记录挪到 /root/gotmp/user-keys-rotation-backup-20260912.json(600)。 - 轮换过程本身也踩了一个小坑:sqlite3 CLI 里没有 gen_random_uuid() (那是网关 Go 驱动注册的函数),插入必须显式给 key_id —— 而当时旧行已经删掉了, 于是出现了一小段「无可用 key」的空档(立刻补上并双向验证过)。
63 lines
3.1 KiB
Bash
63 lines
3.1 KiB
Bash
#!/usr/bin/env bash
|
||
# L2 端到端验证脚本
|
||
set -euo pipefail
|
||
# 管理员 user key。**不要把它写进这个文件**。
|
||
#
|
||
# 2026-09-12:本文件原来硬编码了一把 jianf 的 user key(自 1759666 起在 git 历史里)。
|
||
# 已轮换作废(旧值实测 /auth/me → 401),新值只存在 /root/gotmp/verify-l2-token.txt(600)。 —— 仓库是会被看到的地方,
|
||
# 而写进 git 历史的密钥只能靠轮换作废(删掉当前行不能把它从历史里拿掉)。
|
||
#
|
||
# 取法(任一):
|
||
# VERIFY_L2_TOKEN=<key> bash scripts/verify-l2.sh
|
||
# echo <key> > /root/gotmp/verify-l2-token.txt && chmod 600 该文件
|
||
TOKEN="${VERIFY_L2_TOKEN:-}"
|
||
if [ -z "$TOKEN" ] && [ -r /root/gotmp/verify-l2-token.txt ]; then
|
||
TOKEN=$(tr -d '\n' < /root/gotmp/verify-l2-token.txt)
|
||
fi
|
||
if [ -z "$TOKEN" ]; then
|
||
echo "需要管理员 user key:设 VERIFY_L2_TOKEN,或写到 /root/gotmp/verify-l2-token.txt(600)" >&2
|
||
exit 2
|
||
fi
|
||
BASE="http://127.0.0.1:8180/api/v1"
|
||
H=(-H "Authorization: Bearer $TOKEN")
|
||
PASS=0 FAIL=0
|
||
|
||
ok() { echo " ✅ $1"; PASS=$((PASS+1)); }
|
||
bad() { echo " ❌ $1"; FAIL=$((FAIL+1)); }
|
||
|
||
echo "=== L2 端到端验证 ==="
|
||
|
||
# ── 1. PUT /sessions/:id/permission
|
||
SID=$(sqlite3 /opt/agentmail/data/agentmail.db "SELECT session_id FROM sessions ORDER BY updated_at DESC LIMIT 1;")
|
||
echo "1. PUT /sessions/:id/permission ($SID)"
|
||
|
||
# 改 plan
|
||
R=$(curl -s -X PUT "$BASE/sessions/$SID/permission" -H 'Content-Type: application/json' "${H[@]}" -d '{"permission_mode":"plan"}')
|
||
if echo "$R" | grep -q '"permission_mode":"plan"'; then ok "plan 写入成功"; else bad "plan 写入失败: $R"; fi
|
||
|
||
# 改 full
|
||
R=$(curl -s -X PUT "$BASE/sessions/$SID/permission" -H 'Content-Type: application/json' "${H[@]}" -d '{"permission_mode":"full"}')
|
||
if echo "$R" | grep -q '"permission_mode":"full"'; then ok "full 写入成功"; else bad "full 写入失败: $R"; fi
|
||
|
||
# 脏值 → 回落到 workspace
|
||
R=$(curl -s -X PUT "$BASE/sessions/$SID/permission" -H 'Content-Type: application/json' "${H[@]}" -d '{"permission_mode":"bogus"}')
|
||
if echo "$R" | grep -q '"permission_mode":"workspace"'; then ok "脏值回落到 workspace"; else bad "脏值未回落: $R"; fi
|
||
|
||
# 复原
|
||
curl -s -X PUT "$BASE/sessions/$SID/permission" -H 'Content-Type: application/json' "${H[@]}" -d '{"permission_mode":"workspace"}' > /dev/null
|
||
|
||
# ── 2. calendar_events.permission_mode 列
|
||
echo "2. calendar_events.permission_mode 列"
|
||
COL=$(sqlite3 /opt/agentmail/data/agentmail.db "PRAGMA table_info(calendar_events);" | grep permission_mode || true)
|
||
if [ -n "$COL" ]; then ok "列存在: $COL"; else bad "列不存在"; fi
|
||
|
||
# ── 3. 建会话检查 schema 两列
|
||
echo "3. sessions permission_mode/enforcement 列"
|
||
PM=$(sqlite3 /opt/agentmail/data/agentmail.db "PRAGMA table_info(sessions);" | grep permission_mode || true)
|
||
PE=$(sqlite3 /opt/agentmail/data/agentmail.db "PRAGMA table_info(sessions);" | grep permission_enforcement || true)
|
||
if [ -n "$PM" ]; then ok "permission_mode 列存在"; else bad "permission_mode 列缺失"; fi
|
||
if [ -n "$PE" ]; then ok "permission_enforcement 列存在"; else bad "permission_enforcement 列缺失"; fi
|
||
|
||
echo ""
|
||
echo "=== 结果: $PASS 通过, $FAIL 失败 ==="
|