# 주제: grpc-policy 의 주요 타입이 블록 *안에서도* 대부분 쓰이지 않는다 # revision: 21234e38cdb9a926cbc92bb97a2aee2e4a7d2916 # EVD-325 는 블록 전체가 배포되지 않는다는 사실이다. 이 파일은 그보다 안쪽의 측정이다: # grpc-policy 가 정의한 것을 grpc 블록의 다른 리프가 쓰는가. # command: git grep -ln "" -- src/grpc src/grpc-advanced | grep -v "grpc-policy/" | wc -l # git grep -nE "new ([a-zA-Z0-9_.]+\.)?\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."