RCA 2026.07.30 4 min read

Agent 등록을 Workload Identity와 TokenReview로 강화하기

공유 bootstrap token에 의존하지 않고 projected ServiceAccount token, TokenReview, Pod·DaemonSet UID와 image digest를 결합해 Agent 신원을 검증한 과정을 정리했습니다.

공유 Bootstrap Token만으로는 부족했다

초기 Agent 등록은 Cluster 단위 Bootstrap Token을 사용했다. 설치가 단순하고 MVP를 검증하기에는 충분했지만 운영 환경에서는 다음 질문에 답하기 어려웠다.

  • 등록 요청이 실제 대상 Cluster의 Pod에서 온 것인가
  • 예상한 ServiceAccount와 DaemonSet이 맞는가
  • 다른 Node가 같은 이름으로 등록 정보를 덮어쓸 수 있는가
  • 허용한 Agent Image가 실행 중인가
  • 등록 이후 Credential을 Cluster와 Node에 제한할 수 있는가

그래서 Agent Protocol v2에서는 최초 등록 Identity와 등록 후 Node Credential을 분리했다.

두 가지 등록 Mode

Mode 용도
bootstrap_token 초기 설치와 호환 배포
kubernetes_token_review Kubernetes Workload Identity 검증

운영 환경의 기본 방향은 kubernetes_token_reviewbootstrap_fallback_allowed=false다. 등록이 끝나면 Heartbeat, Evidence와 Realtime Event는 Node-scoped Bearer Token만 사용한다.

TokenReview만 호출한다고 끝나지 않는다

Agent는 전용 Audience의 Projected ServiceAccount Token을 Platform에 제출한다. Platform은 별도로 Mount한 Reviewer Credential로 Kubernetes TokenReview API를 호출한다.

중요한 점은 Agent가 보낸 API URL, CA, Node Metadata를 신뢰하지 않는 것이다. TokenReview를 통과한 뒤에도 다음 Kubernetes Object를 다시 확인한다.

  1. Audience, ServiceAccount Subject·UID와 Group
  2. Pod Name·UID
  3. Pod가 Running이며 삭제 중이 아닌지
  4. Namespace, ServiceAccount와 Node Name
  5. 필수 Label
  6. Controller Owner의 DaemonSet Name·UID
  7. 실행 중인 Agent Container의 ImageID Digest

Projected Token의 Audience는 Kubernetes API Audience와 분리했다.

Agent Enrollment: cluster-infra-rca-agent-enrollment
Kubernetes API:   https://kubernetes.default.svc

두 Audience가 겹치면 Platform은 Profile 저장과 Production 기동을 거부한다. Agent 등록용 Token이 Kubernetes API 인증에도 사용되는 경계를 막기 위해서다.

UID 때문에 두 단계로 Binding하기

ServiceAccount와 DaemonSet UID는 실제 배포 후에 만들어진다. 따라서 Enrollment Profile을 두 단계로 저장한다.

1. Staged Profile

API Server, CA, Audience, Namespace, ServiceAccount, Reviewer 경로와 예상 Label을 저장한다. UID와 Digest가 비어 있으면 workload_identity_ready=false이며 Agent 등록을 막는다.

2. Immutable Identity Binding

Manifest를 적용한 뒤 ServiceAccount UID, DaemonSet UID와 실행 Image Digest를 확인해 Profile에 결합한다.

ServiceAccount UID
DaemonSet UID
Pod UID와 Node Name
Image sha256 Digest

모든 값이 채워져야 등록을 허용한다. 같은 Node 이름에 활성 Identity가 있으면 다른 Pod UID가 덮어쓸 수 없다.

등록 후 Token도 Profile에 묶기

발급된 Node Token은 Cluster, Node와 Enrollment Profile Version에 결합한다. Profile의 보안 필드가 바뀌면 Version을 올리고 기존 Node Token을 폐기한다.

Opaque Token 원문은 DB에 저장하지 않고 HMAC-SHA-256 Hash로 검증한다. Pepper를 교체할 때는 이전 Key를 읽을 수 있는 Key Ring을 먼저 배포하고, 새 Key로 쓰기 전환한 뒤 인증 시 Lazy Rehash를 수행한다.

Reader 준비
  → Writer 전환
  → Lazy Rehash
  → 이전 Key 사용 여부 확인
  → Previous Key 제거

Rolling Update 중 구버전과 신버전 Replica가 서로의 Token을 읽지 못하는 시간을 만들지 않기 위해서다.

외부 Cluster Reviewer Credential 회전

Platform과 대상 Cluster가 다르면 외부 Reviewer Token을 전용 Read-only Mount 경로로 제공한다. Raw Token은 DB, API와 Audit에 남기지 않고 경로와 Version만 관리한다.

새 Credential을 먼저 검증한 뒤 Current로 전환하고, 기존 Credential은 제한된 Grace 동안 Previous로 둔다. Current 파일 읽기 실패 또는 Kubernetes API 401/403에서만 한 번 Fallback한다. 검증이 끝나면 운영자가 Previous를 명시적으로 Retire한다.

이 구조를 선택한 이유

Kubernetes TokenReview는 Token이 유효하다는 사실을 알려준다. 하지만 RCA Agent가 기대한 DaemonSet, Node와 Image에서 실행 중이라는 사실까지 자동으로 보장하지는 않는다.

그래서 Token 검증에 Kubernetes Object Identity와 배포 Artifact Digest를 결합했다. 설정은 복잡해졌지만 공유 Token 하나보다 사고 범위를 Cluster와 Node, Workload Version으로 줄일 수 있었다.

프로젝트 저장소: Kubernetes Cluster Infra RCA Platform