RCA 2026.07.30 4 min read

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

공유 Bootstrap Token으로 확인할 수 없던 Agent 신원을 TokenReview와 Pod·DaemonSet UID, 이미지 Digest로 검증하도록 등록 절차를 바꿨다.

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

처음에는 Cluster 단위 Bootstrap Token으로 Agent를 등록했다. 설치와 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_review와 bootstrap_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가 겹치면 Profile 저장과 Production 기동을 거부하도록 했다. 등록용 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 제거

이 순서로 구버전과 신버전 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한다.

이 구조를 선택한 이유

TokenReview로 Token의 유효성을 확인한 뒤에도 Agent가 어떤 DaemonSet, Node, Image에서 실행되는지는 더 확인해야 했다.

그래서 Kubernetes Object Identity와 배포 Artifact Digest를 등록 조건에 추가했다. 설정할 항목은 늘었지만 Credential을 Cluster, Node, Workload Version에 묶어 영향 범위를 줄였다.

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

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 ↑ ↓ 결과 이동