CKS — 쿠버네티스 보안 전문가 · 클러스터 하드닝 · 이론
권한은 왜 조용히 커지는가
한 줄 요약
RBAC 은 권한 상승을 기본적으로 막지만, escalate·bind·impersonate 세 동사와 자동으로
마운트되는 ServiceAccount 토큰이 그 방어선을 우회합니다. 하드닝은 이 네 개의 구멍을 닫는 일입니다.
왜 이게 필요했나
RBAC 에는 내장 보호 장치가 있습니다. 사용자가 Role 이나 RoleBinding 을 만들려면 그 Role 에
담긴 모든 권한을 이미 갖고 있어야 합니다. 이 규칙 덕분에 "권한이 낮은 사람이 자기에게 높은
권한을 부여하는" 경로가 막힙니다. 문제는 이 보호를 명시적으로 뚫는 동사가 존재한다는 것입니다.
| 동사 | 무엇을 뚫는가 | 실무 대응 |
| --- | --- | --- |
| escalate | 자신이 갖지 않은 권한을 Role 에 추가할 수 있다 | 플랫폼 관리자만, 감사 로그 필수 |
| bind | 자신이 갖지 않은 권한의 Role 을 바인딩할 수 있다 | ClusterRoleBinding 생성 권한 자체를 제한 |
| impersonate | 다른 사용자·그룹·SA 로 가장할 수 있다 | 대상을 resourceNames 로 못 박고 감사 |
여기에 system:masters 그룹이 있습니다. 이 그룹의 멤버는 RBAC 검사를 통째로 우회합니다.
kubeconfig 하나가 유출되면 그것으로 끝입니다. break-glass 절차 전용으로만 두고, 평소에는
아무도 이 그룹에 없어야 합니다.
어떻게 동작하나
두 번째 축은 ServiceAccount 토큰입니다. 파드는 기본적으로 자기 네임스페이스의 default
ServiceAccount 로 실행되고, 그 토큰은 /var/run/secrets/kubernetes.io/serviceaccount/token
으로 자동 마운트됩니다. 애플리케이션이 쿠버네티스 API 를 쓰지 않아도 마운트됩니다. 즉 파드가
하나 뚫리면 공격자는 즉시 클러스터 API 자격증명 하나를 손에 넣습니다.
끄는 방법은 두 곳입니다. ServiceAccount 오브젝트의 automountServiceAccountToken: false,
그리고 파드 스펙의 같은 필드입니다. 파드 레벨 설정이 ServiceAccount 레벨을 덮어씁니다.
그래서 실무에서는 양쪽 다 씁니다. default SA 를 꺼 두면 새 워크로드가 실수로 토큰을 받는
경로가 사라지고, 필요한 워크로드만 전용 SA 를 만들어 명시적으로 켭니다.
토큰의 형태도 바뀌었습니다. 예전에는 SA 마다 만료 없는 토큰 Secret 이 자동 생성됐고, 그 Secret
을 읽을 수 있는 사람은 영원히 유효한 자격증명을 얻었습니다. 지금은 TokenRequest API 로
수명과 대상(audience)이 붙은 토큰을 발급하며, 파드에는 projected volume 의serviceAccountToken 소스로 주입됩니다. 수동으로 만드는kubernetes.io/service-account-token Secret 은 여전히 만들 수 있지만, 만료가 없으므로
꼭 필요할 때만 씁니다.
세 번째는 검증입니다. RBAC 은 눈으로 읽어서 검증하기 어렵습니다. kubectl auth can-i 에--as=system:serviceaccount:<네임스페이스>:<이름> 을 붙이면 그 주체가 실제로 무엇을 할 수
있는지 API 서버가 직접 답해 줍니다. 설계가 아니라 결과를 확인하는 유일한 방법입니다.
현장에서 만나는 모습
정책 엔진을 얹은 조직에서 자주 나오는 P0 장애가 하나 있습니다. OPA Gatekeeper 의
ValidatingWebhook 이 failurePolicy: Fail 로 등록된 상태에서 Gatekeeper 파드가 전부
내려가면, API 서버가 웹훅 응답을 못 받아 대상 리소스의 생성·수정을 전부 거부합니다.
정책을 지키려다 클러스터 배포가 통째로 멈추는 것입니다. 응급 조치는 웹훅 설정 오브젝트를
지우는 것이고, 근본 대응은 프로덕션에서 failurePolicy: Ignore 를 쓰되 Gatekeeper 다운을
반드시 알림으로 잡는 것입니다. 권한을 조이는 장치가 가용성 사고의 원인이 될 수 있다는 사실이
하드닝 설계의 현실적인 제약입니다.
저자의 홈랩에서 컨트롤 플레인을 1 대에서 3 대로 늘릴 때도 자격증명 수명이 문제였습니다.kubeadm init phase upload-certs 는 CA 키 묶음을 암호화해 클러스터 안 Secret 으로 올리고,certificate-key 는 그 암호문을 푸는 대칭키입니다. 이 Secret 은 2 시간 뒤 자동 삭제됩니다.
CA 키가 클러스터 안에 암호화 상태로나마 존재하는 시간을 최소화하려는 설계이고, 같은 원리가
SA 토큰에도 그대로 적용됩니다. 자격증명은 숨기는 것보다 수명을 줄이는 쪽이 거의 항상
효과적입니다.
다음 실습에서 할 것
와일드카드를 가진 ClusterRole 을 클러스터에서 직접 찾아 목록으로 만들고, 위험 동사를 가진
역할을 따로 뽑아냅니다. 그다음 좁힌 Role 을 만들어 ServiceAccount 에 바인딩하고auth can-i --as= 로 결과를 확인합니다. 마지막으로 파드와 default ServiceAccount 양쪽에서
토큰 자동 마운트를 끕니다.