Skip to content

spec.apiKey가 선언만 되고 컨트롤러에 미배선(silent no-op) — Qdrant 인증 미적용 #4

Description

@eightynine01

요약

QdrantClusterSpec.apiKey(*SecretKeyRef)는 CRD·Go 타입에 선언만 돼 있고 컨트롤러가 이 필드를 전혀 읽지 않는다. CR에 spec.apiKey를 지정해도 StatefulSet에 QDRANT__SERVICE__API_KEY가 주입되지 않아 Qdrant는 계속 무인증으로 기동한다. 사용자에게는 "API 키를 걸었다"는 착각을 주는 silent no-op이며, v0.2.1에서 고쳤던 retentionPolicy unwired(API 선언만 있고 STS 매핑 0)와 동일 계열의 함정이다.

실측 근거 (main 77eafb0, v0.6.0)

  1. 참조 부재rg 'APIKey' --glob '*.go' 결과는 api/v1alpha1/qdrantcluster_types.go(선언)와 zz_generated.deepcopy.go(생성물)뿐. internal/ 컨트롤러·리소스 빌더에서 소비하는 곳 0건.
  2. env 미주입internal/resources/statefulset.go:88 컨테이너 EnvQDRANT_INIT_FILE_PATH 하나뿐. QDRANT__SERVICE__API_KEY 없음.
  3. 라이브 대조data/keiailab-qdrant-cluster STS env = [QDRANT_INIT_FILE_PATH], 라이브 CR spec.apiKey = null. (라이브는 애초에 apiKey 미지정이라 회귀가 아니라 기능 자체의 부재)

현재 완화(mitigation): NetworkPolicy / Cilium 실효 통제

이 갭이 지금 사고로 이어지지 않는 이유는 네트워크 계층이 접근을 막고 있기 때문이며, 이는 실측으로 확인했다.

  • Cilium enable-non-default-deny-policies=true, default-ns-zerotrust CNP 가동. 실측: 허용 목록 밖(default ns) 임시 파드에서 keiailab-qdrant-cluster.data.svc:6333연결 timeout(차단).
  • qdrant 접근은 소비자 측 egress 화이트리스트로만 열린다: services/aethelgard-zerotrust, services/toonmixer-publication, traders/traders-scheduler (→ 6333/TCP).
  • ⇒ 무단 네임스페이스로부터의 노출은 실효적으로 막혀 있어 긴급도는 낮다(P2).

잔여 리스크 (네트워크 통제로 못 막는 것)

  • 허용된 소비자 ns의 워크로드는 qdrant에 무인증 전체 접근 — 컬렉션 삭제·스냅샷·설정 변경 등 파괴적 REST/gRPC까지 제한이 없다.
  • 소비자 앱 하나가 침해되면 그 egress 경로를 타고 qdrant 전체가 lateral movement 표적이 된다.
  • NetworkPolicy는 L3/L4(누가 연결 가능한가) 계층이라 application-level authz(무엇을 할 수 있는가)를 대체하지 못한다. apiKey는 다중 소비자·최소권한을 위한 별개 계층이며, network policy와 상호 배타가 아니라 보완 관계다.

구현 시 결정 포인트

  1. 키 종류 — qdrant 1.18은 단일 service.api_key와 별도 service.read_only_api_key를 지원한다. 소비자별 최소권한(읽기 전용 소비자 vs 쓰기 소비자)을 노출하려면 SecretKeyRef를 2개(rw/ro)로 확장할지 결정 필요.
  2. TLS 병행spec.config.tlsEnabled가 이미 존재. 평문 위에 API 키만 얹으면 토큰이 스니핑에 노출되므로, TLS와 함께 문서화/게이팅할지 결정.
  3. 배선 위치statefulset.go의 컨테이너 EnvQDRANT__SERVICE__API_KEY(+ 필요 시 __READ_ONLY_API_KEY)를 SecretKeySelector로 주입. config/initialize.sh의 env 소비 방식 확인(readOnlyRootFilesystem=true·config passthrough 제약 하에서). production.yaml service.api_key와 env 간 우선순위 정합.
  4. 관측statusauthEnabled류 필드 노출 여부.

수용 기준(제안)

  • CR에 apiKey 지정 → STS env에 QDRANT__SERVICE__API_KEY 주입 → 무인증 요청이 401.
  • envtest는 PVC GC 케이스처럼 이 갭을 못 잡는다(선언 ≠ 배선). 따라서 격리 스테이징 실전 검증(무인증 401 실측)을 수용 기준에 포함.

발견 경위: data ns 라이브 qdrant의 인증 상태 점검 중 CRD 선언과 컨트롤러 배선 불일치를 확인. 완화책인 NetworkPolicy의 실효성(default ns 차단)은 실측으로 검증함.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestsecurity보안 취약점·하드닝 관련

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions