LabHub
배우기 러닝패스 코스

Kubernetes運用実務

トークンの寿命とオーディエンスを扱う

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

파드의 신원이 어떻게 발급되고 어떤 수명과 대상을 갖는지 직접 확인하고, 필요 없는 토큰은 아예 주지 않는 설정을 적용합니다.

왜 중요한가

컨테이너가 뚫렸을 때 공격자가 가장 먼저 찾는 것이 /var/run/secrets/kubernetes.io/serviceaccount 의 토큰입니다. 그래서 이 모듈의 핵심 질문은 두 개입니다 — 이 파드가 정말 토큰이 필요한가, 그리고 그 토큰은 언제 만료되는가. 1.24 이전의 방식은 두 질문 모두에 나쁜 답을 갖고 있었습니다. 어카운트를 만들면 만료 없는 토큰이 자동으로 생겼고, 파드는 필요 여부와 무관하게 그것을 마운트받았습니다. 지금은 파드가 받는 토큰이 수명을 갖고 kubelet 이 갱신하며, automountServiceAccountToken: false 로 아예 끌 수도 있습니다. 여기에 audience 가 더해지면 토큰이 "어디에 쓸 것인지"까지 담아, Vault 에 주려고 발급한 토큰이 다른 곳에서 재사용되는 것을 막습니다. 이 구조가 그대로 클라우드 워크로드 아이덴티티로 이어져 정적 키 자체를 없애는 설계가 됩니다. 마지막으로 잊지 마세요. 신원을 만들었다고 권한이 생기지는 않습니다. 권한은 여전히 RBAC 가 정합니다.

단계

  1. 네임스페이스 sa-lab 을 만들고 그 안에 ServiceAccount payments 를 만드세요. 이 어카운트에는 자동 생성된 Secret 이 붙어 있으면 안 됩니다. 그리고 /root/ops/sa/out/sa-note.txt 에 왜 요즘은 시크릿이 자동으로 생기지 않는지를 한 줄로 적으세요(1.24 이후 단기 토큰으로 바뀐 배경, 만료·수명 같은 표현이 들어가야 합니다).
  2. sa-lab 에 파드 payments-api 를 만들되 spec.serviceAccountNamepayments 로 지정하세요. 기본 설정이면 서비스 어카운트 토큰이 담긴 projected 볼륨이 자동으로 붙습니다.
  3. ServiceAccount lockedautomountServiceAccountToken: false 로 만드세요. 그리고 파드 hardened 를 만들되 spec.serviceAccountNamelocked, spec.automountServiceAccountTokenfalse 로 하세요. 이 파드에는 토큰 볼륨이 하나도 붙어 있으면 안 됩니다.
  4. payments 어카운트의 토큰을 수명 1시간(3600초), 대상 vault 로 발급하고, 그 JWT 의 페이로드를 디코딩한 JSON/root/ops/sa/out/token.json 에 저장하세요. 이 JSON 에는 subsystem:serviceaccount:sa-lab:payments 이고, aud 가 비어 있지 않으며, expiat 의 차이가 약 3600 초이고, kubernetes.io 클레임이 들어 있어야 합니다.
  5. sa-lab 에 파드 projected-demo 를 만드세요. spec.serviceAccountNamepayments 로 하고, projected 볼륨에 serviceAccountToken 소스를 두되 audience: vault, expirationSeconds: 3600, path: vault-token 으로 지정하세요. 첫 번째 컨테이너는 이 볼륨을 /var/run/secrets/vault 경로로 마운트해야 합니다.
  6. sa-lab 에 Secret payments-legacy-token 을 만드세요. typekubernetes.io/service-account-token, 어노테이션 kubernetes.io/service-account.namepayments 입니다. 그리고 /root/ops/sa/out/legacy-note.txt 에 이 방식이 왜 권장되지 않는지를 60바이트 이상, 두 문장 정도로 적으세요(만료가 없다는 점과 폐기·로테이션 부담이 들어가야 합니다).
  7. payments 어카운트에 최소 권한만 주세요. sa-lab 에서 ConfigMap 을 getlist 할 수 있어야 하고, Secret 을 읽거나 ConfigMap 을 삭제할 수는 없어야 합니다. 권한은 payments 를 주체로 하는 RoleBinding 으로 연결하세요.
  8. /root/ops/sa/out/sa-audit.json 을 만드세요. pods 는 배열이며 sa-lab 의 실제 파드 개수와 정확히 일치해야 합니다. 각 원소는 name, service_account, automount 세 필드를 갖습니다. payments-apiservice_accountpayments 여야 하고, hardenedautomountfalse 여야 하며, service_accountdefault 인 파드는 하나도 없어야 합니다. 마지막으로 recommendations 배열에 개선 권고를 2개 이상 적으세요.

참고

전용 서비스 어카운트 만들기

네임스페이스 sa-lab 을 만들고 그 안에 ServiceAccount payments 를 만드세요. 이 어카운트에는 자동 생성된 Secret 이 붙어 있으면 안 됩니다. 그리고 /root/ops/sa/out/sa-note.txt 에 왜 요즘은 시크릿이 자동으로 생기지 않는지를 한 줄로 적으세요(1.24 이후 단기 토큰으로 바뀐 배경, 만료·수명 같은 표현이 들어가야 합니다).

요즘 버전에서는 어카운트를 만들어도 시크릿이 딸려 오지 않습니다. 왜 그렇게 바뀌었는지를 한 줄로 정리해 두세요.

파드에 전용 어카운트 지정하기

sa-lab 에 파드 payments-api 를 만들되 spec.serviceAccountNamepayments 로 지정하세요. 기본 설정이면 서비스 어카운트 토큰이 담긴 projected 볼륨이 자동으로 붙습니다.

파드 명세에서 어카운트를 지정하는 필드 이름을 확인하세요. 지정하면 토큰 볼륨이 자동으로 붙습니다.

토큰 자동 마운트 끄기

ServiceAccount lockedautomountServiceAccountToken: false 로 만드세요. 그리고 파드 hardened 를 만들되 spec.serviceAccountNamelocked, spec.automountServiceAccountTokenfalse 로 하세요. 이 파드에는 토큰 볼륨이 하나도 붙어 있으면 안 됩니다.

같은 필드를 파드에도, 어카운트에도 쓸 수 있습니다. 껐다면 볼륨 목록에 토큰이 남아 있으면 안 됩니다.

단기 토큰 발급하고 페이로드 뜯어보기

payments 어카운트의 토큰을 수명 1시간(3600초), 대상 vault 로 발급하고, 그 JWT 의 페이로드를 디코딩한 JSON/root/ops/sa/out/token.json 에 저장하세요. 이 JSON 에는 subsystem:serviceaccount:sa-lab:payments 이고, aud 가 비어 있지 않으며, expiat 의 차이가 약 3600 초이고, kubernetes.io 클레임이 들어 있어야 합니다.

JWT 는 점으로 나뉜 세 조각이고 가운데가 페이로드입니다. base64url 이라 패딩을 맞춰야 디코딩됩니다. 수명은 두 시각의 차이로 확인하세요.

대상이 지정된 projected 토큰 쓰기

sa-lab 에 파드 projected-demo 를 만드세요. spec.serviceAccountNamepayments 로 하고, projected 볼륨에 serviceAccountToken 소스를 두되 audience: vault, expirationSeconds: 3600, path: vault-token 으로 지정하세요. 첫 번째 컨테이너는 이 볼륨을 /var/run/secrets/vault 경로로 마운트해야 합니다.

토큰에 대상을 박으면 그 대상에서만 유효합니다. 파일 이름과 마운트 경로를 정확히 맞추세요.

레거시 장기 토큰 시크릿 만들고 위험 정리하기

sa-lab 에 Secret payments-legacy-token 을 만드세요. typekubernetes.io/service-account-token, 어노테이션 kubernetes.io/service-account.namepayments 입니다. 그리고 /root/ops/sa/out/legacy-note.txt 에 이 방식이 왜 권장되지 않는지를 60바이트 이상, 두 문장 정도로 적으세요(만료가 없다는 점과 폐기·로테이션 부담이 들어가야 합니다).

특정 타입과 어노테이션이 있어야 컨트롤러가 토큰을 채워 줍니다. 이 방식의 진짜 문제는 편의가 아니라 만료가 없다는 점입니다.

어카운트에 최소 권한만 주기

payments 어카운트에 최소 권한만 주세요. sa-lab 에서 ConfigMap 을 getlist 할 수 있어야 하고, Secret 을 읽거나 ConfigMap 을 삭제할 수는 없어야 합니다. 권한은 payments 를 주체로 하는 RoleBinding 으로 연결하세요.

어카운트를 만드는 것과 권한을 주는 것은 별개입니다. 필요한 것만 열고 나머지는 확인으로 막혀 있는지 검증하세요.

어카운트 사용 현황 감사하기

/root/ops/sa/out/sa-audit.json 을 만드세요. pods 는 배열이며 sa-lab 의 실제 파드 개수와 정확히 일치해야 합니다. 각 원소는 name, service_account, automount 세 필드를 갖습니다. payments-apiservice_accountpayments 여야 하고, hardenedautomountfalse 여야 하며, service_accountdefault 인 파드는 하나도 없어야 합니다. 마지막으로 recommendations 배열에 개선 권고를 2개 이상 적으세요.

파드 수는 실제 클러스터와 정확히 맞아야 합니다. default 어카운트를 쓰는 파드가 하나라도 있으면 안 됩니다.