역할 기반 접근 제어 모범 사례
역할 기반 접근 제어 모범 사례 (Role Based Access Control Good Practices)
클러스터 운영자를 위한 좋은 RBAC 설계의 원칙과 관행을 다뤄요.
쿠버네티스 [RBAC]는 클러스터 사용자와 워크로드가 자신의 역할을 수행하는 데 필요한 리소스에만 접근할 수 있도록 보장하는 핵심 보안 제어 장치입니다. 클러스터 사용자의 권한을 설계할 때 클러스터 관리자는 권한 상승(privilege escalation)이 발생할 수 있는 영역을 이해하는 것이 중요해요. 그래야 과도한 접근이 보안 사고로 이어질 위험을 줄일 수 있습니다.
여기에 제시된 모범 사례는 일반적인 [RBAC 문서]와 함께 읽어야 합니다.
일반적인 모범 사례 (General good practice)
최소 권한 (Least privilege)
이상적으로는 사용자와 서비스 계정에 최소한의 RBAC 권한을 할당해야 해요. 명시적으로 운영에 필요한 권한만 사용해야 합니다. 각 클러스터는 다르겠지만, 적용할 수 있는 일반적인 규칙이 몇 가지 있어요.
- 가능하면 네임스페이스 수준에서 권한을 할당하세요. 사용자에게 특정 네임스페이스 안에서만 권한을 주려면 ClusterRoleBindings 대신 RoleBindings를 사용해요.
- 가능하면 와일드카드 권한, 특히 모든 리소스에 대한 와일드카드를 제공하지 마세요. 쿠버네티스는 확장 가능한 시스템이므로, 와일드카드 접근은 클러스터에 현재 존재하는 모든 객체 유형뿐 아니라 미래에 생성될 모든 객체 유형에 대한 권한도 부여하기 때문입니다.
- 관리자는 특별히 필요한 경우가 아니면
cluster-admin계정을 사용하지 마세요. 낮은 권한의 계정에 [impersonation 권한]을 부여하면 클러스터 리소스의 우발적 수정을 피할 수 있어요. system:masters그룹에 사용자를 추가하지 마세요. 이 그룹의 구성원은 모든 RBAC 권한 검사를 우회하며 항상 제한 없는 슈퍼유저 접근을 가지는데, RoleBindings나 ClusterRoleBindings를 제거해도 이를 되돌릴 수 없어요. 덧붙여, 클러스터가 권한 부여 webhook을 사용한다면 이 그룹의 구성원 자격은 그 webhook도 우회합니다 (이 그룹 구성원의 요청은 webhook로 보내지지 않아요).
특권 토큰의 배포 최소화 (Minimize distribution of privileged tokens)
이상적으로 Pod에는 강력한 권한(예: 권한 상승 위험 항목에 나열된 권한 중 어떤 것)이 부여된 서비스 계정을 할당하지 않아야 해요. 워크로드가 강력한 권한을 필요로 하는 경우 다음 관행을 고려하세요.
- 강력한 권한을 가진 Pod를 실행하는 노드 수를 제한하세요. 실행하는 DaemonSet이 필요한지 확인하고, 컨테이너 탈출의 폭발 반경(blast radius)을 제한하기 위해 최소 권한으로 실행하세요.
- 강력한 권한을 가진 Pod를 신뢰할 수 없거나 공개적으로 노출된 Pod 옆에서 실행하지 마세요. [Taints and Toleration], [NodeAffinity], [PodAntiAffinity]를 사용해 Pod가 신뢰할 수 없거나 신뢰도가 낮은 Pod 옆에서 실행되지 않도록 하세요. 특히 신뢰도가 낮은 Pod가 Restricted Pod Security Standard를 충족하지 못하는 상황에 주의하세요.
하드닝 (Hardening)
쿠버네티스는 기본적으로 모든 클러스터에서 필요하지 않을 수 있는 접근을 제공합니다. 기본으로 제공되는 RBAC 권한을 검토하면 보안 하드닝 기회를 찾을 수 있어요. 일반적으로 system: 계정에 부여된 권한은 변경해서는 안 되지만, 클러스터 권한을 하드닝하는 몇 가지 옵션이 있어요.
system:unauthenticated그룹에 대한 바인딩을 검토하고 가능하면 제거하세요. 이 그룹은 네트워크 수준에서 API 서버에 접근할 수 있는 모든 사람에게 접근을 주기 때문입니다.automountServiceAccountToken: false설정으로 서비스 계정 토큰의 기본 자동 마운트를 피하세요. 자세한 내용은 [기본 서비스 계정 토큰 사용]을 참고하세요. Pod에 대해 이 값을 설정하면 서비스 계정 설정을 덮어쓰며, 서비스 계정 토큰이 필요한 워크로드는 여전히 마운트할 수 있어요.
주기적 검토 (Periodic review)
쿠버네티스 RBAC 설정의 중복 항목과 가능한 권한 상승을 주기적으로 검토하는 것은 매우 중요해요. 공격자가 삭제된 사용자와 같은 이름의 사용자 계정을 만들면, 그 삭제된 사용자의 모든 권한(특히 그 사용자에게 할당된 권한)을 자동으로 상속할 수 있습니다.
쿠버네티스 RBAC - 권한 상승 위험 (Kubernetes RBAC - privilege escalation risks)
쿠버네티스 RBAC에는 부여되면 사용자나 서비스 계정이 클러스터 안에서 권한을 상승시키거나 클러스터 밖의 시스템에 영향을 줄 수 있는 여러 권한이 있어요.
이 섹션은 클러스터 운영자가 실수로 의도한 것보다 더 많은 접근을 허용하지 않도록 주의해야 할 영역을 보여주기 위한 것입니다.
시크릿 나열 (Listing secrets)
Secrets에 대한 get 접근을 허용하면 내용을 읽을 수 있게 된다는 것은 일반적으로 분명해요. list와 watch 접근도 실제로는 Secret 내용을 드러낼 수 있게 한다는 점을 아는 것도 중요합니다. 예를 들어 List 응답(kubectl get secrets -A -o yaml 등을 통해)이 반환되면 그 응답은 모든 Secrets의 내용을 포함합니다.
워크로드 생성 (Workload creation)
네임스페이스에서 워크로드를 생성할 권한(Pod 또는 Pod를 관리하는 [workload resource])을 부여하면, 해당 네임스페이스의 Secrets, ConfigMaps, Pod에 마운트할 수 있는 PersistentVolumes 같은 다른 많은 리소스에도 암묵적으로 접근 권한이 부여됩니다. 또한 Pod는 어떤 [ServiceAccount]로든 실행될 수 있으므로, 워크로드 생성 권한을 부여하면 그 네임스페이스의 모든 서비스 계정의 API 접근 수준도 암묵적으로 부여됩니다.
특권 Pod를 실행할 수 있는 사용자는 그 접근을 사용해 노드 접근을 얻고 잠재적으로 권한을 더 상승시킬 수 있어요. 사용자나 다른 주체가 적절히 안전하고 격리된 Pod를 만들 수 있다고 완전히 신뢰하지 않는 경우, Baseline 또는 Restricted Pod Security Standard를 강제해야 합니다. [Pod Security admission]이나 다른 (서드파티) 메커니즘을 사용해 이를 구현할 수 있어요.
이런 이유로 네임스페이스는 서로 다른 신뢰 수준이나 테넌시가 필요한 리소스를 분리하는 데 사용해야 합니다. 최소 권한 원칙을 따르고 최소한의 권한 집합을 할당하는 것이 여전히 모범 관행이지만, 네임스페이스 안의 경계는 약하다고 간주해야 해요.
영구 볼륨 생성 (Persistent volume creation)
누군가 또는 어떤 애플리케이션이 임의의 PersistentVolume을 생성할 수 있다면, 그 접근에는 hostPath 볼륨 생성이 포함되어, Pod가 관련 노드의 기본 호스트 파일시스템에 접근하게 됩니다. 이런 능력을 부여하는 것은 보안 위험입니다.
호스트 파일시스템에 제한 없는 접근을 가진 컨테이너가 권한을 상승시킬 수 있는 방법은 여러 가지예요. 다른 컨테이너의 데이터를 읽거나, Kubelet 같은 시스템 서비스의 자격 증명을 남용하는 것을 포함합니다.
PersistentVolume 객체 생성 접근은 다음에게만 허용해야 합니다.
- 작업에 이 접근이 필요하고 신뢰하는 사용자(클러스터 운영자)
- 자동 프로비저닝이 구성된 PersistentVolumeClaim을 기반으로 PersistentVolume을 생성하는 쿠버네티스 컨트롤 플레인 컴포넌트. 이는 보통 쿠버네티스 프로바이더나 운영자가 CSI 드라이버를 설치할 때 설정합니다.
영구 저장소 접근이 필요한 곳에서는 신뢰받는 관리자가 PersistentVolume을 만들고, 제한된 사용자는 PersistentVolumeClaim을 사용해 그 저장소에 접근해야 합니다.
Node의 proxy 하위 리소스 접근 (Access to proxy subresource of Nodes)
nodes/proxy 하위 리소스에 접근할 수 있는 사용자는 권한이 있는 노드의 모든 Pod에서 명령을 실행할 수 있게 해주는 Kubelet API에 대한 권한을 가져요. 이 접근은 감사 로깅과 admission control을 우회하므로 이 리소스에 권한을 부여하기 전에 주의해야 합니다. 이 API는 웹소켓 HTTP GET 요청으로 실행될 수 있는데, 이는 단지 get 동사의 권한 부여만 필요해요. 즉 nodes/proxy에 대한 get 권한은 읽기 전용 권한이 아니라는 뜻입니다. 예를 들어 nodes/proxy에 대한 get 권한은, 호출자가 쿠버네티스 API를 통한 동등한 권한이 없더라도 컨테이너 로그를 검색하거나 pod 프로세스에 실행/연결할 수 있는 특권 kubelet API에 접근을 제공합니다.
자세한 내용은 [Kubelet authentication/authorization]을 참고하세요.
escalate 동사 (Escalate verb)
일반적으로 RBAC 시스템은 사용자가 가진 권한보다 더 많은 권한을 가진 clusterroles를 생성하는 것을 방지해요. 이 규칙의 예외는 escalate 동사입니다. [RBAC 문서]에 언급된 것처럼, 이 권한이 있는 사용자는 실제로 자신의 권한을 상승시킬 수 있어요.
bind 동사 (Bind verb)
escalate 동사와 비슷하게, 이 권한을 부여하면 사용자가 권한 상승에 대한 쿠버네티스 내장 보호를 우회하여, 아직 가지지 않은 권한을 가진 역할에 대한 바인딩을 만들 수 있게 됩니다.
impersonate 동사 (Impersonate verb)
이 동사는 사용자가 클러스터의 다른 사용자를 impersonate하여 그 권한을 얻을 수 있게 해줘요. 부여할 때 주의해서, impersonate된 계정 중 하나를 통해 과도한 권한을 얻을 수 없도록 해야 합니다.
CSR과 인증서 발급 (CSRs and certificate issuing)
CSR API는 signer가 kubernetes.io/kube-apiserver-client인 certificatesigningrequests/approval에 대한 update 권한과 CSR에 대한 create 권한이 있는 사용자가, 클러스터에 인증할 수 있는 새 클라이언트 인증서를 만들 수 있게 해줍니다. 이 클라이언트 인증서는 쿠버네티스 시스템 컴포넌트의 복제본을 포함한 임의의 이름을 가질 수 있어요. 이는 실제로 권한 상승을 허용하게 됩니다.
토큰 요청 (Token request)
serviceaccounts/token에 대한 create 권한이 있는 사용자는 기존 서비스 계정에 대한 토큰을 발급하는 TokenRequests를 만들 수 있어요.
Admission webhook 제어 (Control admission webhooks)
validatingwebhookconfigurations 또는 mutatingwebhookconfigurations를 제어할 수 있는 사용자는, 클러스터에 입회된(admitted) 모든 객체를 읽을 수 있는 webhook을 제어할 수 있으며, mutating webhook의 경우 입회된 객체를 변형할 수도 있습니다.
네임스페이스 수정 (Namespace modification)
Namespace 객체에 대해 patch 작업을 수행할 수 있는 사용자(그 접근을 가진 Role에 대한 namespaced RoleBinding을 통해)는 그 네임스페이스의 레이블을 수정할 수 있어요. Pod Security Admission이 사용되는 클러스터에서는 이로 인해 사용자가 관리자가 의도한 것보다 더 관대한 정책으로 네임스페이스를 구성할 수 있게 됩니다. NetworkPolicy가 사용되는 클러스터에서는 사용자가 서비스에 대한 간접 접근을 허용하는 레이블을 설정할 수 있는데, 관리자가 의도하지 않았을 수 있어요.
쿠버네티스 RBAC - 서비스 거부 위험 (Kubernetes RBAC - denial of service risks)
객체 생성 서비스 거부 (Object creation denial-of-service)
클러스터에서 객체를 생성할 권한이 있는 사용자는, [etcd used by Kubernetes is vulnerable to OOM attack]에서 논의된 것처럼 객체의 크기나 수에 기반해 서비스 거부 상태를 만들 만큼 충분히 큰 객체를 생성할 수 있어요. 반신뢰 또는 비신뢰 사용자에게 시스템에 대한 제한된 접근이 허용되는 다중 테넌트 클러스터에서 특히 관련이 있을 수 있습니다.
이 문제의 완화 옵션 중 하나는 [리소스 쿼터]를 사용해 생성할 수 있는 객체 수를 제한하는 것입니다.
다음 내용 (What's next)
- RBAC에 대해 더 배우려면 [RBAC 문서]를 참고하세요.