LabHub
배우기 러닝패스 코스

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

신원·수신자·권한은 서로 다른 질문이다

LabHub 에서 이어서 보기

한 줄 요약

토큰이 누구를 나타내는지, 누구에게 보낼 수 있는지, 어떤 일을 허용받는지는 서로 다른 질문입니다.
디코딩 결과나 관리자 대리 요청만으로 세 질문에 모두 답할 수 없습니다.

왜 이게 필요했나

예시 사고입니다. 보고서 서비스에 쓰던 토큰을 Kubernetes API에 보내니 401이 왔습니다.
팀원은 역할에 권한이 빠졌다며 cluster-admin을 붙이자고 합니다. 다른 팀원은 토큰의
만료 시각이 내일이라 서버가 잘못됐다고 합니다. 둘 다 아직 원인을 확인하지 않았습니다.
수신자가 다른 토큰이라면 권한을 늘려도 해결되지 않고, 불필요한 권한만 남습니다.

이 단원의 개인 VM에는 같은 이름의 reader 계정이 두 네임스페이스에 있습니다.
각 계정은 자기 네임스페이스의 lesson-policy ConfigMap 한 개만 읽습니다.
데이터는 training-only라는 합성 문자열입니다. 민감한 비밀 없이도 인증과 인가의
차이를 재현할 수 있으므로, 실제 서비스 토큰을 가져와 연습할 이유가 없습니다.

어떻게 동작하나

발급·검증·사용을 따로 관측한다

TokenRequest는 서비스 계정의 자격증명을 발급받는 요청입니다. 요청에는 audience와
희망 수명, 필요하면 결합할 객체의 이름과 UID를 넣습니다. 응답의 실제 만료 시각을
확인해야 하며 요청한 숫자가 언제나 그대로 적용된다고 가정하지 않습니다.
이번에는 관리자가 교육용 계정의 토큰을 발급합니다. 이 관리자의 발급 권한과
발급된 토큰 주체의 ConfigMap 읽기 권한은 별개입니다.

JWT의 가운데 부분을 base64url 디코딩하면 sub·aud·exp 같은 클레임을 읽을 수 있습니다.
하지만 서명까지 확인한 것은 아닙니다. 종이에 적힌 사번을 읽는 것과 발급 기관에
신분증 진위를 확인하는 것은 다릅니다. 토큰 내용을 읽었다고 검증 완료라고 쓰지 않습니다.

TokenReview는 토큰의 인증 결과를 물을 때 사용합니다. 이번 도우미는 관리자 요청으로
그 검사를 수행하되 토큰 원문 대신 인증 여부, audience, username, UID만 보여줍니다.
이 결과가 true라도 해당 사용자의 ConfigMap 조회를 허용했다는 뜻은 아닙니다.
실제 읽기 요청을 따로 보내야 역할과 바인딩의 결과까지 확인할 수 있습니다.

요청에 다른 신분증을 섞지 않는다

관리자 kubeconfig를 사용하는 kubectl에 옵션 하나만 추가하고 서비스 계정의 행동이라고
부르면 실험이 애매해집니다. 이번 GET 클라이언트는 관리자 클라이언트 인증서를 쓰지 않고
Authorization의 bearer 토큰만 사용합니다. 서버 CA 검증은 유지하고 리다이렉트와 proxy는
사용하지 않습니다. 어떤 주소로 어떤 자격증명이 갔는지가 실험의 일부입니다.

관리자에게 허용된 --as 대리 요청은 RBAC를 점검하는 데 유용합니다. 그러나 그 요청에는
검사하려는 옛 토큰의 서명·audience·만료 여부가 들어 있지 않습니다. 대리 요청이 성공했다는
결과를 토큰 유효성의 증거로 재사용하지 않는 것이 이번 단원의 출발점입니다.

audience 실험을 읽는 법

이 VM의 API는 labhub-kcsa-api를 수신자로 사용합니다. labhub-kcsa-report를 지정해
발급한 토큰은 이 API의 ConfigMap 읽기에서 401이 됩니다. 같은 토큰을 보고서 수신자로
명시해 TokenReview하면 인증 결과는 true가 됩니다. 토큰이 통째로 고장 난 것이 아니라
어느 수신자에게 제시했는지가 달랐던 것입니다. 이는 이 단원의 실제 k3s 탐침에서 확인한 결과입니다.

외부 보고서 서비스가 존재한다고 가정한 예시이지, 이번 실습에서 보고서 서버를 배포한 것은
아닙니다. 실제 서비스라면 허용할 audience를 서버 설정으로 정하고 그 범위로 검사해야 합니다.
요청자가 보낸 audience를 무조건 받아들이는 검사는 수신자 구분의 목적을 잃습니다.

현장에서 만나는 모습

먼저 요청 주소와 자격증명 종류를 확인하고, 다음으로 수신자·만료·인증 결과를 봅니다.
인증이 된 뒤에 대상 자원·동사·네임스페이스와 RBAC를 확인합니다. 모든 403이 같은
원인이라고 단정하지 말고 응답 이유와 요청 주체를 함께 남깁니다. 익명 요청이 항상
401인 것도 아니므로 이번 잘못된 bearer의 관측을 모든 요청에 일반화하지 않습니다.

Pod와 SA의 automountServiceAccountToken을 false로 두는 것은 자동 토큰 마운트를
피하는 설정입니다. 관리자에게 TokenRequest 발급 권한이 없어지는 설정이 아닙니다.
이번 Pod는 자동 마운트를 끄고 토큰을 명시적으로 발급해 두 효과를 섞지 않습니다.
일반적인 projected token은 kubelet이 회전하지만, 이번에 파일로 저장한 토큰을
kubelet이 대신 갱신해 주지는 않습니다. 두 전달 방식을 구분해 운영해야 합니다.

다음 레슨으로 연결

다음 글에서는 계정 재생성으로 UID가 바뀌는 상황을 살펴봅니다. 그다음 실습에서
자기 자원 200·다른 팀 자원 403을 기준선으로 만들고, 다른 audience 토큰을 제시했을 때의
401과 TokenReview 결과를 비교합니다. 토큰 원문을 터미널·보고서·게시판에 붙이지 않습니다.
클레임과 해시만 기록하고, 디코딩·인증·인가 중 어느 관측인지 옆에 표시하세요.

공식문서