LabHub
배우기 러닝패스 코스

KCSA — 쿠버네티스 보안 어소시에이트 · 서비스 계정 신원과 토큰의 수명 · 실습

계정을 다시 만들었는데 왜 권한이 살아 있을까

LabHub 에서 이어서 보기

목표

실제 bearer 토큰으로 audience·인증·인가를 분리하고, SA를 동명 재생성했을 때 옛 토큰과 이름 기반 바인딩의 동작을 비교합니다.

왜 중요한가

권한 회수와 자격증명 폐기는 같은 일이 아닙니다. 계정 이름만 보고 대응 완료를 판단하면 새 신원에 기존 권한이 다시 적용될 수 있습니다.
관리자 대리 요청이 아닌 TokenRequest·TokenReview와 CA를 검증하는 실제 HTTPS GET으로 확인합니다.
개인 k3s VM 안의 합성 ConfigMap만 사용합니다. 운영 kubeconfig나 실제 비밀을 가져오지 마세요.
환경 준비에 수분이 걸릴 수 있습니다. 55분 실습이며 더 필요하면 만료 전에 연장하세요. VM·파일·토큰은 세션 종료 시 회수됩니다.
필요한 관측만 미리 내려받고 토큰 원문은 내려받거나 공유하지 마세요.

준비된 환경과 도구

입력 JSON만 직접 작성합니다. 토큰 발급 결과는 도우미가 /opt/fixtures/kcsa-identity-tokens 안에 0600으로 보관하며 원문을 출력하지 않습니다.
이 파일들은 개인 실습 내부의 재료이지 편집하거나 보고서에 붙일 답안이 아닙니다. 수동 발급 토큰의 요청 수명은 3시간이며 서버 응답으로 실제 만료를 확인합니다.
내부 기준선 /opt/fixtures/kcsa-identity-context.json과 /opt/fixtures/kcsa-identity-lab-context.json은 도우미가 관리합니다. 삭제·편집하지 마세요.
act는 지정된 변경만 수행합니다. capture는 관측 조건을 확인한 뒤 /root/kcsa-identity에 JSON을 저장합니다.
observe는 현재 관측만 출력하고 grade는 자원·학생 파일을 바꾸지 않습니다. TokenReview는 토큰 검증 API이며 저장형 객체 생성이 아닙니다.

단계

1. capture 1로 /root/kcsa-identity/baseline.json을 저장하세요. kcsa-identity의 reader SA, identity-client Pod, named-config-reader Role·RoleBinding과 lesson-policy ConfigMap의 UID를 조사합니다. Pod와 SA의 자동 토큰 마운트는 false이며 다른 팀 kcsa-identity-other의 정상 접근을 유지해야 합니다.
2. /root/kcsa-identity/old-request.json에 authentication.k8s.io/v1 TokenRequest를 작성하세요. spec.audiences는 ["labhub-kcsa-api"], expirationSeconds는 10800, boundObjectRef는 apiVersion=v1, kind=Pod, name=identity-client와 1단계에서 관측한 실제 Pod UID입니다. act 2로 발급하고 capture 2로 bound-token.json에 해시·클레임·검증 신원을 기록합니다. 토큰 원문은 출력하지 마세요.
3. capture 3으로 /root/kcsa-identity/scoped-request.json을 저장하세요. 원래 bearer 토큰으로 자기 lesson-policy 조회가 200, 다른 팀 조회가 403인지 확인합니다. 관리자 인증서나 --as 요청을 이 증거로 대신하지 않습니다.
4. /root/kcsa-identity/report-request.json에 2단계와 같은 TokenRequest를 작성하되 audiences를 ["labhub-kcsa-report"]로 바꾸세요. act 4와 capture 4로 audience.json을 저장합니다. 이 토큰의 API GET은 401, 기본 TokenReview는 false, 보고서 audience를 명시한 TokenReview는 true여야 합니다.
5. /root/kcsa-identity/deny-role.json에 rbac.authorization.k8s.io/v1 Role을 작성하세요. 이름은 named-config-reader, 네임스페이스는 kcsa-identity, rules는 빈 배열입니다. act 5와 capture 5로 rbac-revoked.json을 저장합니다. 바인딩과 SA UID는 유지되고 원래 토큰 인증은 true, 조회는 403이어야 합니다.
6. /root/kcsa-identity/restore-role.json에 같은 Role을 작성하되 rules에 apiGroups=[""], resources=["configmaps"], resourceNames=["lesson-policy"], verbs=["get"]인 규칙 한 개를 넣으세요. act 6으로 Role을 복원하고 원래 SA를 UID 전제 조건으로 삭제·동명 재생성합니다. capture 6으로 uid-revoked.json을 저장하세요. 기존 Pod·바인딩 UID는 유지하고 SA UID는 변경되며 옛 토큰은 만료 전에 인증 false·401이어야 합니다.
7. /root/kcsa-identity/new-request.json에 2단계와 같은 API audience·수명·원래 Pod UID의 TokenRequest를 작성하세요. act 7과 capture 7로 new-identity.json을 저장합니다. 새 토큰의 sub는 같지만 SA UID는 다르며 기존 바인딩으로 조회 200, 옛 토큰은 계속 401이어야 합니다.
8. act 8로 조사한 원래 RoleBinding만 UID·resourceVersion 전제 조건을 사용해 제거하세요. capture 8로 /root/kcsa-identity/closed.json을 저장합니다. 새 토큰 인증 true·조회 403, 옛 토큰 401, 다른 팀 신원·ConfigMap UID 유지와 정상 조회 200을 함께 확인합니다.

참고

토큰 디코딩은 서명 검증이 아니며 관리자 --as 요청은 해당 bearer 토큰의 수신자·만료 검사가 아닙니다.
이미 진행한 단계는 파일·구성을 보존합니다. 과거 기록을 지운 뒤 현재 상태로 같은 성공 기록을 다시 만들지 않습니다.
뒤 단계로 진행한 뒤 과거 단계는 저장 당시의 토큰 수명으로 검증하며 현재 단계의 실제 상태도 별도로 확인합니다.
새 단계 관측 전에 바로 앞 단계의 기록과 입력 파일을 보존하세요. 다른 팀의 SA·Role·바인딩·ConfigMap과 자기 Pod·Role·ConfigMap UID는 끝까지 보존합니다.
단계 준비는 없는 이전 입력·관측만 만들고 현재 답이나 미완성 입력을 덮어쓰지 않습니다.
도우미가 기다리는 제한에 걸리면 같은 VM의 observe와 상태를 조사하세요. 설치를 반복하거나 권한을 넓혀 해결하지 않습니다.
SA 삭제는 다른 토큰에도 영향을 줄 수 있습니다. 이 실험을 운영의 무조건적인 대응 순서로 사용하지 마세요.
401·403은 이번 인증된 요청의 맥락에서 읽습니다. 모든 익명 요청이 401이라는 뜻은 아닙니다.
관측 기록은 학습 자료이지 root를 통제하는 원격 증명·부정행위 방지 장치가 아닙니다.
공식문서: [ServiceAccount 토큰](https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/) ·
[이름·네임스페이스 기반 RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/).

단계 8개

  1. 기준선 신원과 보안 설정 조사
  2. 실제 Pod UID에 결합한 토큰 발급
  3. 실제 요청의 네임스페이스 경계
  4. 수신자가 다른 토큰 비교
  5. 권한 회수와 인증 유지
  6. 같은 이름의 새 서비스 계정
  7. 새 신원과 기존 바인딩 연결
  8. 정확한 권한 회수와 영향 확인