docs: replace prose placeholders in reproduction steps with executable commands
The audit found ~80 placeholders, and the damaging ones were where the measuring apparatus itself was prose rather than a command: a6 "( curl ... ) & 를 20개 띄우고 wait" — the 22.2s headline came from this a3 "<로그인 반복, sid 를 /tmp/sids 에>" — the whole RPO measurement a3 "<sid 목록>" — the control it is compared against a5 "<수신 파드IP>" — the injection a8 writes /tmp/tok, reads /tmp/rt — self-inconsistent, sent an empty token b3 $KC / $RT / $NEW never assigned c2 bare kcadm.sh with no kubectl exec a1 conntrack tuples written by hand, though the direction flips per restart Each is now a shell-expandable form: pod IPs from jsonpath, the admin password from the secret, ids from kcadm --format csv, conntrack tuples derived from "conntrack -L" with awk rather than transcribed. Then the rewritten commands were executed against the live cluster, and one of them failed — the 20-way load generator, written as "kubectl run --rm -i", lost its output stream twice in a row. That is a trap this series already hit once, and the rewrite reintroduced it. A-6 now uses a resident probe pod that collects into a file and is cat-ed once; verified 20/20 lines. Evidence: docs/evidence/followup/05-command-reproducibility.txt Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
f3f3a8da46
commit
74c9b3cea7
@@ -124,7 +124,7 @@ DB 로 확인했다.
|
||||
select us.user_session_id,
|
||||
(select count(*) from offline_client_session cs
|
||||
where cs.user_session_id = us.user_session_id) as client_sessions
|
||||
from offline_user_session us where us.user_session_id = '<sid>';
|
||||
from offline_user_session us where us.user_session_id = '$SID';
|
||||
```
|
||||
|
||||
```
|
||||
@@ -300,22 +300,37 @@ A-0 에서 Keycloak 자신이 `for no key update skip locked` 를 쓰는 이유
|
||||
kubectl -n keycloak-lab exec keycloak-0 -- /opt/keycloak/bin/kcadm.sh \
|
||||
update realms/keycloak-patterns -s revokeRefreshToken=true -s refreshTokenMaxReuse=0
|
||||
|
||||
# 2. refresh token 하나 확보 (direct grant)
|
||||
curl -s -X POST $KC -d grant_type=password -d client_id=bff-confidential \
|
||||
-d client_secret=bff-lab-secret -d username=labuser -d password=labpass -d scope=openid
|
||||
# 2. refresh token 하나 확보 (direct grant). 이후 단계가 전부 이 변수들을 쓴다.
|
||||
KC=http://keycloak.keycloak-lab.svc:8080/realms/keycloak-patterns/protocol/openid-connect/token
|
||||
R=$(curl -s -X POST $KC -d grant_type=password -d client_id=bff-confidential \
|
||||
-d client_secret=bff-lab-secret -d username=labuser -d password=labpass -d scope=openid)
|
||||
RT=$(echo "$R" | sed -n 's/.*"refresh_token":"\([^"]*\)".*/\1/p')
|
||||
SID=$(echo "$R" | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p' | cut -d. -f2 \
|
||||
| sed 's/$/==/' | base64 -d 2>/dev/null | sed -n 's/.*"sid":"\([^"]*\)".*/\1/p')
|
||||
echo "SID=$SID"
|
||||
|
||||
# 3. 동시에 5개 — & 와 wait 이 없으면 재현되지 않는다
|
||||
i=1; while [ $i -le 5 ]; do ( curl ... -d refresh_token=$RT > /tmp/c$i ) & i=$((i+1)); done; wait
|
||||
# 3. 동시에 5개 — & 와 wait 이 없으면 재현되지 않는다(순차로는 경합이 생기지 않는다)
|
||||
i=1
|
||||
while [ $i -le 5 ]; do
|
||||
( curl -s -o /tmp/c$i -w '%{http_code}\n' -X POST $KC \
|
||||
-d grant_type=refresh_token -d client_id=bff-confidential \
|
||||
-d client_secret=bff-lab-secret -d refresh_token=$RT ) &
|
||||
i=$((i+1))
|
||||
done
|
||||
wait
|
||||
|
||||
# 4. ★ 이긴 요청의 토큰을 다시 써본다 — 여기서 진짜 답이 나온다
|
||||
curl -s -o /dev/null -w '%{http_code}' -X POST $KC -d grant_type=refresh_token -d refresh_token=$NEW
|
||||
NEW=$(cat /tmp/c1 /tmp/c2 /tmp/c3 /tmp/c4 /tmp/c5 \
|
||||
| sed -n 's/.*"refresh_token":"\([^"]*\)".*/\1/p' | head -1)
|
||||
curl -s -o /dev/null -w '%{http_code}\n' -X POST $KC -d grant_type=refresh_token \
|
||||
-d client_id=bff-confidential -d client_secret=bff-lab-secret -d refresh_token=$NEW
|
||||
|
||||
# 5. 기제 확인 — client session 이 지워졌는지
|
||||
kubectl -n keycloak-lab exec deploy/postgres -- psql -U keycloak -d keycloak -c \
|
||||
"select us.user_session_id,
|
||||
(select count(*) from offline_client_session cs
|
||||
where cs.user_session_id = us.user_session_id) as client_sessions
|
||||
from offline_user_session us where us.user_session_id = '<sid>'"
|
||||
from offline_user_session us where us.user_session_id = '$SID'"
|
||||
|
||||
# 6. 정책 비교 — revokeRefreshToken 과 refreshTokenMaxReuse 를 바꿔가며 3~5 반복
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user