dev.to

Kubernetes RBAC Explained by Breaking It: Practice Roles and Bindings in Your Browser

Kubernetes RBAC을 직접 깨뜨리며 익히기: 브라우저에서 Roles와 Bindings 실습

Kubernetes RBAC에서 권한 범위는 Role의 종류만으로 정해지지 않습니다. Role이 허용할 동작을 정하고 Binding이 적용 범위를 정한다는 규칙을 일곱 가지 실패 사례로 설명하며, 브라우저 시뮬레이터와 kubectl auth can-i로 권한을 확인하는 방법을 안내합니다.

에디터 노트

권한을 허용하는 테스트만으로는 범위가 제대로 제한됐는지 확인하기 어렵습니다. 글은 dev에서 Pod 조회가 성공하는지뿐 아니라 prod에서는 거부되는지도 확인해야 한다고 강조하며, ClusterRole을 RoleBinding으로 연결하면 해당 네임스페이스에만 권한이 적용된다는 사례로 이를 보여줍니다. 댓글은 이 점을 PostgreSQL RLS의 테넌트 격리 검사와 연결합니다. 시뮬레이터는 권한을 부여한 Binding과 거부한 이유를 함께 보여줘 기본 규칙을 익히는 데 유용하지만, 권한 상승 경로는 다루지 않습니다. Secret 조회, 워크로드 생성, escalate와 bind 같은 권한은 별도로 살펴야 한다는 글의 범위가 분명합니다.

AI 요약

Kubernetes RBAC을 이해할 때 먼저 기억할 규칙은 "Role은 무엇을 허용하는지, Binding은 어디에 적용하는지 정합니다"입니다. ClusterRole을 RoleBinding으로 dev 네임스페이스에 연결하면 해당 권한은 dev에만 적용됩니다. ClusterRole이라는 이름만 보고 모든 네임스페이스에 권한이 퍼진다고 판단하면 안 됩니다. 반대로 ClusterRoleBinding은 ClusterRole 권한을 모든 네임스페이스와 클러스터 범위 리소스에 부여합니다. 글쓴이는 이 차이를 일곱 가지 시나리오로 직접 확인하도록 만든 무료 브라우저 도구 Kubernetes RBAC Simulator를 소개합니다. 도구 제작에 참여했다는 공개도 덧붙입니다.

RBAC 네 가지 객체와 규칙

Role은 한 네임스페이스에 속하는 규칙 목록이며, ClusterRole은 네임스페이스 없이 규칙을 정의합니다. ClusterRole은 여러 네임스페이스에서 재사용하거나 nodes 같은 클러스터 범위 리소스의 권한을 표현할 때 씁니다. RoleBinding은 자신의 네임스페이스 안에서 Role 또는 ClusterRole을 사용자, 그룹, 서비스 계정에 연결합니다. ClusterRoleBinding은 ClusterRole을 모든 네임스페이스와 클러스터 범위 리소스에 연결합니다.

각 규칙은 apiGroups, resources, verbs로 구성하며 resourceNames로 특정 객체에 한정할 수도 있습니다. 권한은 더해지기만 하며 deny 규칙은 없습니다. 따라서 어떤 주체가 특정 작업을 할 수 있는지 확인하려면 그 주체를 지정한 Binding을 찾고, 해당 Binding이 현재 위치에서 요청한 권한을 부여하는지 살펴봅니다.

일곱 가지 사례로 권한 범위 확인

시뮬레이터는 Role과 Binding을 YAML로 보여주고, 주체와 동사, 리소스, 네임스페이스, 선택적 객체 이름을 지정하게 합니다. 결과는 Allowed 또는 Denied로 표시됩니다. 허용한 Binding과 Role을 밝히고, 요청을 허용하지 않은 Binding도 이유와 함께 보여줍니다. 해당 리소스에서 주체가 가진 전체 동사 목록과 같은 질의를 실행하는 kubectl auth can-i 명령도 제공합니다.

첫 사례에서는 dev의 Role과 RoleBinding으로 dev의 Pod 목록을 읽습니다. 두 번째 사례는 같은 서비스 계정에 ClusterRole을 RoleBinding으로 연결한 뒤 prod의 Pod 목록을 요청합니다. 결과는 거부입니다. ClusterRole의 규칙은 여러 곳에서 재사용할 수 있지만 RoleBinding이 권한을 dev에 한정하기 때문입니다. Binding의 namespace가 권한을 부여할 위치를 결정합니다.

세 번째 사례에서는 nodes 권한을 가진 ClusterRole을 RoleBinding으로 연결합니다. nodes는 클러스터 범위 리소스이므로 네임스페이스에 한정된 Binding으로 접근 권한을 줄 수 없습니다. 네 번째 사례는 resourceNames: ["db-password"]와 get 동사만 허용합니다. 지정한 Secret은 읽을 수 있지만 list는 거부됩니다. 이름을 지정하지 않은 일반 목록 요청도 허용되지 않습니다. 단, list 또는 watch 규칙에 resourceNames가 있을 때 metadata.name 필드 선택자가 일치하면 허용될 수 있다는 문서상 예외가 있습니다.

다섯 번째 사례는 Binding의 roleRef에 pod-reader 대신 존재하지 않는 pod-readr를 적은 경우입니다. 이 연결은 권한을 주지 않습니다. bind 권한 보유자나 system:masters 구성원은 역할 조회를 건너뛸 수 있어 잘못된 참조를 오류 없이 적용할 수 있지만, 실제 요청은 권한 거부와 함께 존재하지 않는 Role 이름을 알립니다. roleRef는 생성 뒤 수정할 수 없으므로 Binding을 삭제하고 다시 만들어야 합니다. 여섯 번째 사례에서는 권한이 있는 Binding과 빈 Role을 가리키는 Binding을 함께 둡니다. 빈 Role은 기존 권한을 취소하지 않습니다. RBAC에는 deny 규칙이 없으므로 사라진 권한을 찾기보다 어떤 허용 규칙이 없는지 확인해야 합니다. 마지막 사례는 ClusterRole을 ClusterRoleBinding으로 연결해 kube-system의 Pod 목록을 허용합니다.

권한 확인과 위험한 권한

시뮬레이터는 권한 상승 경로를 다루지 않습니다. 글은 Kubernetes RBAC 모범 사례 문서를 바탕으로 별도 점검할 권한을 짚습니다. Secret에 대한 list 또는 watch는 응답에 Secret 데이터가 들어갈 수 있어 내용을 노출합니다. Pod나 Deployment, Job처럼 워크로드를 만드는 권한은 해당 네임스페이스의 Secret, ConfigMap, 볼륨을 연결하거나 그곳의 서비스 계정으로 실행하는 길을 열 수 있습니다. escalate와 bind는 자신이 가진 범위를 넘는 권한 부여를 막는 검사를 우회하며, impersonate는 다른 주체로 행동하게 합니다. 이 동사들은 시뮬레이터의 선택 항목에 없으므로 Role에서 직접 확인해야 합니다. 와일드카드도 함께 살펴야 합니다. 기본 제공 edit ClusterRole에는 Secret 읽기와 서비스 계정 impersonate 권한이 포함되며, ClusterRoleBinding으로 연결하면 적용 범위가 모든 네임스페이스로 넓어집니다.

kubectl auth can-i로 시뮬레이터의 질의를 실제 클러스터에 확인할 수도 있습니다. --as는 다른 주체로 권한을 확인하는 기능이라 impersonate 권한이 필요하며, -n을 생략하면 현재 네임스페이스를 기준으로 답합니다. 클러스터 범위 리소스에서는 -n이 혼란을 일으킬 수 있습니다. 글쓴이는 Kubernetes API 서버 v1.37.1에서 nodes 질의에 -n dev를 넣자 can-i가 경고와 함께 yes를 출력했지만, 실제 kubectl get nodes 요청은 클러스터 범위에서 Forbidden으로 거부됐다고 설명합니다. 이 경우 --all-namespaces로 질의해야 하며, --list와는 함께 쓸 수 없습니다. 글쓴이는 일곱 사례의 실제 API 요청 결과가 시뮬레이터 결과와 같았다고 덧붙입니다.

dev.to 반응

  • @cekuu35 — "Role은 무엇을, Binding은 어디에"라는 규칙은 전체를 설명하며 SQL 권한 부여와 RLS에도 거의 그대로 대응합니다. 같은 사람들을 똑같이 헷갈리게 합니다. "권한은 더해지기만 하고 deny 규칙은 없다"는 점도 PostgreSQL과 같습니다. 허용하는 권한이나 USING (true) 정책이 있으면 나중에 "deny"를 추가해 취소할 수 없습니다. 그래서 ClusterRoleBinding으로 kube-system까지 열어 문제를 해결하려는 반응은 공유 테이블에 허용적인 정책을 붙이는 실수와 같습니다. 또 하나 공통으로 가르칠 점은 거부되는 상황도 확인해야 한다는 것입니다. CI 계정이 dev에서 Pod를 읽는지만 시험하고 prod에서 거부되는지는 확인하지 않는 경우가 많습니다. RBAC에서는 Forbidden을 예상해야 하고, RLS에서는 다른 테넌트의 조회 결과가 0행이어야 합니다. RoleBinding도 ClusterRole을 연결할 수 있으므로 "ClusterRole이니까"라는 말만으로 적용 범위를 알 수 없습니다. 범위는 Binding이 정합니다. 시뮬레이터에서 안전하게 권한을 깨뜨려 볼 수 있는 점은 더하기만 하는 규칙을 익히는 빠른 방법입니다.

원문: dev.to / 번역·요약: Trawling