The keycloak project ended with four open questions that design could not
settle. A two-VM lab was built to answer them by measurement, and this is
that material: 26 experiments, 125 raw command outputs, 22 browser captures.
Follows the import procedure in README.md.
source/ the originating repository verbatim — 78 documents, 28 SVGs,
8 manifests, plus .source-revision recording the commit
final/ the SSOT
document.md 729 lines written from the 29 experiment documents, not
concatenated: what was predicted, what was measured, and
where the measurement itself was wrong
evidence/raw 125 outputs, flattened to <experiment>__<file> because
the originals collided (01-baseline.txt appeared three
times) and the audit only globs the top level
evidence/meta one per raw file; command and exitCode are null and the
README says why rather than inventing them
evidence/browser 22 captures
assets/ three diagrams through techviz
.techviz/ their VizSpecs
A separate project rather than an addition to keycloak: the B-layer answers
that project's four questions, but the A, C and D layers are about cluster
failure, SSO and operations, and one document.md should hold one subject.
The four question records there can point here through 관계.
Recorded rather than papered over: only three of the 28 diagrams were
remade. The repository forbids hand-drawn SVG and forbids titles inside the
canvas; all 28 originals carry both, so converting them is redrawing, not
reformatting. They stay in source/ and the gap is written into the document.
verify-pipeline.py passes. audit-records.py reports no issues.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
52 lines
3.5 KiB
Plaintext
52 lines
3.5 KiB
Plaintext
# 주제: grpc-policy 의 주요 타입이 블록 *안에서도* 대부분 쓰이지 않는다
|
|
# revision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916
|
|
|
|
# EVD-325 는 블록 전체가 배포되지 않는다는 사실이다. 이 파일은 그보다 안쪽의 측정이다:
|
|
# grpc-policy 가 정의한 것을 grpc 블록의 다른 리프가 쓰는가.
|
|
|
|
# command: git grep -ln "<T>" -- src/grpc src/grpc-advanced | grep -v "grpc-policy/" | wc -l
|
|
# git grep -nE "new ([a-zA-Z0-9_.]+\.)?<T>\s*\(" -- src | grep "/src/main/" | wc -l
|
|
타입 다른 리프 파일 src/main 생성
|
|
GrpcTlsProfile 8 3 <- 널리 쓰임
|
|
GrpcErrorMapper 3 1
|
|
GrpcContextBinder 1 1
|
|
GrpcRetryCoordinator 0 0 <- 블록 안에서도 미사용
|
|
GrpcIdempotencyInterceptor 0 0 <-
|
|
GrpcResumeTokenCodec 0 0 <-
|
|
ProtovalidateGrpcInterceptor 0 0 <-
|
|
GrpcCompletionReconciler 0 0 <-
|
|
GrpcCredentialRotationManager 0 0 <-
|
|
GrpcSerializedStreamWriter 0 0 <-
|
|
# => 표본 10개 중 7개가 자기 리프 밖 참조 0, src/main 생성 0 이다.
|
|
# grpc-policy 는 62개 main 파일 7,581 LOC 로 블록 최대 리프인데,
|
|
# 그 대부분이 자기 테스트에서만 실행된다.
|
|
|
|
# ---- 재개 토큰의 구분자 처리 (messaging PlanDigest 와의 대비) ----
|
|
# GrpcResumeTokenCodec 은 payload 를 '|' 로 join 하고 HMAC 서명한다.
|
|
# encode: Base64( canonicalPayload + "|" + Base64(HMAC(payload)) )
|
|
# decode: lastIndexOf('|') 로 payload/signature 분리
|
|
# FIELD_SEPARATOR.split(payload, -1) 의 길이가 정확히 9가 아니면 Optional.empty()
|
|
#
|
|
# GrpcResumeToken 의 String 필드 5개(streamId, snapshotVersion, callerFingerprint,
|
|
# filterFingerprint, signingKeyId)는 GrpcIdentifiers.requireBounded 로 검증되는데,
|
|
# 그 검사는 제어문자와 공백만 금지한다 — '|' 는 허용한다.
|
|
#
|
|
# 그러나 **디코드가 정확히 9개 필드를 요구하므로** 필드에 '|' 가 섞인 토큰은
|
|
# 10개 이상으로 쪼개져 거절된다. 두 다른 필드 조합이 같은 payload 문자열을 만들어도
|
|
# (예: streamId="a|b",snapshot="c" 와 streamId="a",snapshot="b|c")
|
|
# 양쪽 다 10개로 쪼개져 어느 쪽도 디코드되지 않는다.
|
|
# => fail-closed 다. 혼동이 아니라 사용 불가가 된다.
|
|
#
|
|
# 대조: messaging 의 ReplayPlan.digest()/RedrivePlan.digest() 도 String.join("|") 을 쓰지만
|
|
# 그 결과는 **해시될 뿐 디코드되지 않으므로** 개수 검사가 없다.
|
|
# 거기서는 단사성이 "자유 형식 필드가 하나뿐" 이라는 조건에 의존한다(EVD-304).
|
|
# 같은 구분자 기법이 한쪽에서는 개수 검사로 닫히고 다른 쪽에서는 우연에 의존한다.
|
|
|
|
# ---- decode 가 세 실패를 구별하지 않는 이유 ----
|
|
# GrpcResumeTokenCodec.decode javadoc:
|
|
# "@return empty when the token is malformed, signed by an unknown key, or does not verify. The
|
|
# three are deliberately indistinguishable to a caller: telling them apart is a probing oracle."
|
|
# 그리고 알 수 없는 key id 에 대해 현재 키로 폴백하지 않는다:
|
|
# "A codec that retries verification with every key it holds turns key rotation into a
|
|
# window in which a token signed by a compromised key still verifies."
|