본문 바로가기

Docker & Kubenetes

쿠버네티스 역할 기반 접근 제어 (RBAC)

쿠버네티스 RBAC는 클러스터 사용자나 워크로드가 역할을 수행하기 위해 필요한 자원에 대한 접근 권한을 통제하는 핵심 보안 제어 방식으로 기본 권한 관리 방법이다.

 

유저가 클러스터에 명령을 날릴때 kubectl명령으로 사용하게 되는데
.kube/config파일에 클러스터와 유저 내용이 리스트 형태( -로 구분 )로 적혀있고 
클러스터와 유저를 매핑한 context를 생성해두면 특정 클러스터의 특정 유저로 접근이 가능하다.


- 현재 사용중인 context는 currunt-context로 알 수 있다.

- 같은 계정을 공유하는 환경이면 서로 다른 context를 사용하거나 수정하면 에러나 충돌이 발생할 수 있다.

- kubectl config get-contexts 명령어로 현재 사용중인 context를 확인할 수 있으며 kubectl config use-context <context명> 으로 사용할 context를 변경할 수 있다.

 

쿠버네티스는 네임스페이스 단위에서 유저 리소스 접근을 핸들링하기 위한 4가지 접근 제어 방식이 존재한다.

- Node : 스케줄링 된 파드의 kubelet에서 접근 제어
- ABAC : 속성 기반 접근 제어
- RBAC : 역할 기반 접근 제어
- Webhook : POST 요청에 대한 접근 제어

- RBAC 특정 역할을 API 엔드포인트로 연결할 때 API 서버와 통신하는 API 그룹으로 관련 기능 요청을 수집한다.

- RBAC는 rbac.authorization.k8s.io API를 사용한다.

- ABAC처럼 마스터에 접근할 필요 없이 kubectl이나 API를 이용해 관리할 수 있다.

롤(Role)

특정 API나 리소스 등 파일에 명시해둔 규칙의 집합이 되며, 특정 네임스페이스에 대한 권한을 관리한다.

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
 
metadata:
  namespace: default
  name: test-pod-reader
 
rules:
- apiGroups: [""] # 핸들링할 API가 포함된 그룹
  resources: ["pods"] # 핸들링할 API 종류
  verbs: ["get", "watch", "list"] # 핸들링하고자 하는 액션
  resourceNames: ["pod-A", "pod-B"] # 핸들링을 허용하는 리소스
 # resourceNames필드를 설정하면 설정된 자원에만 적용되며, create, watch, list 등의
 # rules[].verb 필드 값은 적용되지 않는다.
 
- apiGroups: ["apps"] 
  resources: ["deployment"]
  verbs: ["create", "list"]

롤바인딩(RoleBinding)

롤바인딩은 롤과 특정 사용자를 묶어주는 역할을 수행하고, 지정한 사용자들에 한해서 롤에 명시한 규칙들을 기준으로 권한을 사용할 수 있도록 관리를 할 수 있다.

apiVersion: rbac.authorization.k8s.io/v1
 
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
 
subjects: # 롤을 적용할 유저
- kind: User or Group or ServiceAccount
  name: jane 
  apiGroup: rbac.authorization.k8s.io
 
roleRef: # 유저에게 적용할 롤
  kind: Role 
  name: test-pod-reader 
  apiGroup: rbac.authorization.k8s.io

RBAC 핸들링

롤 목록 확인 : kubectl get role
롤 상세 정보 확인 : kubectl describe role [롤_이름]
롤 바인딩 목록 확인 : kubectl get rolebindings
롤 바인딩 상세 정보 확인 : kubectl describe rolebindings [롤바인딩_이름]
권한 가능 여부 확인 : kubectl auth can-i [액션] [리소스] --as [유저]


클러스터롤(ClusterRole) & 클러스터롤바인딩(ClusterRoleBinding)

클러스터롤과 클러스터롤바인딩을 사용해야 하고 1:N 연결이 가능하다. (클러스터롤과 클러스터롤바인딩은 admin 계정으로만 확인 가능)

apiVersion: rbac.authorization.k8s.io/v1
 
kind: ClusterRole
 
metadata:
  name: secret-reader
 
rules:
- apiGroups: [""] 
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]
apiVersion: rbac.authorization.k8s.io/v1
 
kind: ClusterRoleBinding
 
metadata:
  name: read-secrets-global
 
subjects: # 롤을 적용할 유저
- kind: User or Group or ServiceAccount # 유저 또는 그룹 지정
  name: michelle
  apiGroup: rbac.authorization.k8s.io
 
roleRef: # 유저에게 적용할 롤
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

APP(pod) - Service Account - Rolebinding - Role

kubectl describe rolebinding <rolebinding name> -n <namespace> 하면 특정 롤바인딩에서 명시한 Service Account를 확인할 수 있다, Service Account는 어느 Rolebinding을 가르키는게 아니라 Rolebinding이 Service Account를 가리키는 방식

 

파드 정의의 spec.serviceAccountName 필드에 Service Account의 이름을 명시하여 할당할 수 있다. 서비스어카운트는 반드시 파드가 생성될 때 지정해야 한다. 그 이후에는 변경할 수 없다.

apiVersion: v1
kind: Pod
metadata:
  name: curl-custom-sa
spec:
  serviceAccountName: foo  # default 대신 다른 서비스 어카운트 사용
  containers:
  - name: main
    image: tutum/curl
    command: ["sleep", "9999999"]
  - name: ambassador
    image: luksa/kubectl-proxy:1.6.2

Rolebinding의 YAML

$ kubectl edit rolebinding test -n foo yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: test
  namespace: foo
roleRef:  # 롤바인딩은 service-reader 룰을 참조
  apiGroup: rbac.authorization.k8s.io
  kind: Role  
  name: service-reader
subjects:  # foo 네임스페이스상에서 default 서비스어카운트에 바인드
- kind: ServiceAccount 
  name: default
  namespace: foo
- kind: ServiceAccount
  name: default
  namespace: bar

적용중인 접근제어 종류 확인

vi /etc/kubernetes/manifests/kube-apiserver.yaml 파일의
authorization-mode 부분 확인

 

ClusterRole 핸들링

클러스터롤 목록 확인 : kubectl get clusterrole
클러스터롤 상세 정보 확인 : kubectl describe clusterrole [클러스터롤_이름]
클러스터롤 바인딩 목록 확인 : kubectl get clusterrolebindings
클러스터롤 바인딩 상세 정보 확인 : kubectl describe clusterrolebindings [클러스터롤바인딩_이름]
권한 가능 여부 확인 : kubectl auth can-i [액션] [리소스] --as [유저]

Error from server (Forbidden) : 는 해당 사용자에게 권한이 없다는 에러

바인딩 타입

접근  롤 타입 바인딩 타입
클러스터 수준 리소스
(노드, 영구 볼륨)
clusterrole clusterrolebinding
비리소스 
URL (/api, /healthz, ...)
clusterrole clusterrolebinding
여러 네임스페이스에 있는 네임스페이스 리소스 
(그리고 모든 네임스페이스에 걸쳐있는)
clusterrole clusterrolebinding
특정 네임스페이스에 있는 네임스페이스 리소스 
(다수의 네임스페이스에 동일한 클러스터를 재사용)
clusterrole rolebinding
특정 네임스페이스에 있는 네임스페이스 리소스 
(롤은 각 네임스페이스에서 정의)
role rolebinding

 

모범 사례

최소 권한

- 작업에 명시적으로 필요한 권한만 부여되어야 한다.

- 권한은 가능하면 네임스페이스 레벨에서 부여하고 특정 네임스페이스 내에서만 사용자에게 권한을 부여한다.

- 운영자는 cluster-admin 계정이 필수로 요구되지 않을시에는 사용을 지양한다.

- system:master그룹에 사용자 추가를 지양한다.

 

특정 토큰 분배 최소화

- 강력한 권한이 부여된 서비스 어카운트를 파드에게 지정해서는 안된다.

- 강력한 권한이 부여된 파드를 외부로 노출된 파드와 함께 실행하는 것을 지양한다.

 

하드닝(Hardening)

system:unauthenticated 그룹의 바인딩은 누구에게나 네트워크 레벨에서 API 서버와 통신할 수 있는 권한을 부여하므로 가능하면 제거한다.

 

주기적 검토

쿠버네티스 RBAC 설정을 주기적으로 검토해야한다. 만일 공격자가 삭제된 사용자와 같은 이름으로 사용자 계정을 생성할 수 있다면, 삭제된 사용자의 모든 권한, 특히 해당 사용자에게 부여되었던 권한까지도 자동으로 상속받을 수 있게 된다

 

 

참고 : https://velog.io/@niyu, https://kuberetes.io/ko/docs/concepts/security/rbac-god-practices/