RBACで権限を切る
한국어 원문으로 표시합니다.
목표
ServiceAccount 에 최소 권한을 주고, 그 권한이 네임스페이스 경계를 넘지 않는 것을 확인하고, 클러스터 스코프 권한과 Aggregated ClusterRole 까지 구성합니다.
왜 중요한가
RBAC 문제는 시험에서 배점이 확실합니다. 그런데 정답을 만드는 것보다 정답이 맞는지 확인하는 것이 더 중요합니다. kubectl auth can-i --as= 는 SubjectAccessReview 를 만들어 apiserver 에 물어볼 뿐 실제 요청을 보내지 않으므로, 부작용 없이 몇 번이고 확인할 수 있습니다.
이 실습은 특히 no 를 확인하는 단계를 넣었습니다. RBAC 는 누적만 되고 거부 규칙이 없어서, 실수로 ClusterRoleBinding 을 쓰면 의도한 것보다 훨씬 넓게 열립니다. 열렸는지는 쉽게 확인하지만 안 열렸는지는 잘 확인하지 않습니다. 최소 권한 원칙은 "안 되는 것을 확인하는 습관" 없이는 지켜지지 않습니다.
단계
- 네임스페이스
cka-rbac과cka-rbac-other를 만든다.cka-rbac에 ServiceAccountdeploy-bot을 만들고,cka-rbac-other에는 경계 확인용 ConfigMapboundary-probe를 하나 만든다. cka-rbac에 Rolepod-reader를 만든다. apiGroups 는 core (빈 문자열), resources 는pods와pods/log, verbs 는get,list,watch만.cka-rbac에 RoleBindingpod-reader-bind를 만들어 Rolepod-reader를 ServiceAccountcka-rbac/deploy-bot에 연결한다.deploy-bot으로 가장한 권한 확인 결과를/root/cka-rbac/can-i.txt에 저장한다.cka-rbac에서 파드 get 이 yes 여야 하고 delete 는 no 여야 한다.- 같은 계정으로
cka-rbac-other에서 파드를 읽을 수 있는지 확인해/root/cka-rbac/boundary.txt에 저장한다. 결과는 no 여야 한다. - ClusterRole
node-viewer(apiGroups core, resourcesnodes, verbsget/list/watch)와 ClusterRoleBindingnode-viewer-bind를 만들어cka-rbac/deploy-bot에 연결한다. 노드 list 가 yes 가 되어야 한다. - ClusterRole
cka-monitoring-endpoints를 만든다. 라벨rbac.labhub.io/aggregate-to-monitoring=true, 규칙은 core 그룹의services와endpoints에 대해get,list. 그리고 ClusterRolecka-monitoring을 만들어 aggregationRule 이 그 라벨을 셀렉터로 고르게 한다. cka-rbac에 ServiceAccountno-token을 만들되automountServiceAccountToken: false로 둔다. 파드locked-down(이미지nginx:1.27)을 만들어 serviceAccountName 을no-token으로 하고 파드 스펙에서도automountServiceAccountToken: false를 명시한다. 이 계정에는 아무 권한도 바인딩하지 않는다.
참고
- 서비스어카운트로 가장할 때 이름은
system:serviceaccount:<네임스페이스>:<이름>형식입니다. - 4, 5단계의 파일에는 명령 출력(yes 또는 no)이 그대로 들어 있으면 됩니다.
- 흔한 실수 1: 3단계에서 subjects 에 namespace 를 빼먹는 것. 같은 네임스페이스라도 명시해야 합니다.
- 흔한 실수 2: 6단계를 RoleBinding 으로 하는 것. 노드는 클러스터 스코프라 네임스페이스 바인딩으로는 열 수 없습니다.
서비스어카운트와 실험용 네임스페이스
네임스페이스 cka-rbac 과 cka-rbac-other 를 만든다. cka-rbac 에 ServiceAccount deploy-bot 을 만들고, cka-rbac-other 에는 경계 확인용 ConfigMap boundary-probe 를 하나 만든다.
서비스어카운트는 네임스페이스 스코프입니다. 경계를 확인하려면 접근하면 안 되는 쪽에도 리소스가 하나 있어야 합니다.
읽기 전용 Role 만들기
cka-rbac 에 Role pod-reader 를 만든다. apiGroups 는 core (빈 문자열), resources 는 pods 와 pods/log, verbs 는 get, list, watch 만.
core 그룹은 빈 문자열입니다. 로그는 파드와 별개의 서브리소스로 취급되니 따로 적어야 합니다. 쓰기 동사를 넣으면 안 됩니다.
RoleBinding 으로 연결하기
cka-rbac 에 RoleBinding pod-reader-bind 를 만들어 Role pod-reader 를 ServiceAccount cka-rbac/deploy-bot 에 연결한다.
subjects 의 kind 는 ServiceAccount 이고, 이름과 함께 그 계정이 있는 네임스페이스도 적어야 합니다.
권한이 붙었는지 확인하기
deploy-bot 으로 가장한 권한 확인 결과를 /root/cka-rbac/can-i.txt 에 저장한다. cka-rbac 에서 파드 get 이 yes 여야 하고 delete 는 no 여야 한다.
auth can-i 는 실제 요청을 보내지 않고 물어보기만 합니다. --as 에 넣는 서비스어카운트 이름 형식이 정해져 있습니다.
네임스페이스 경계 넘기 실패 확인
같은 계정으로 cka-rbac-other 에서 파드를 읽을 수 있는지 확인해 /root/cka-rbac/boundary.txt 에 저장한다. 결과는 no 여야 한다.
여기서 yes 가 나온다면 바인딩 종류를 잘못 고른 것입니다. RoleBinding 과 ClusterRoleBinding 의 차이를 다시 보세요.
클러스터 스코프 리소스 열어 주기
ClusterRole node-viewer (apiGroups core, resources nodes, verbs get/list/watch)와 ClusterRoleBinding node-viewer-bind 를 만들어 cka-rbac/deploy-bot 에 연결한다. 노드 list 가 yes 가 되어야 한다.
노드는 어떤 네임스페이스에도 속하지 않습니다. 네임스페이스 스코프 바인딩으로는 접근을 줄 수 없습니다.
Aggregated ClusterRole 구성하기
ClusterRole cka-monitoring-endpoints 를 만든다. 라벨 rbac.labhub.io/aggregate-to-monitoring=true, 규칙은 core 그룹의 services 와 endpoints 에 대해 get, list. 그리고 ClusterRole cka-monitoring 을 만들어 aggregationRule 이 그 라벨을 셀렉터로 고르게 한다.
aggregationRule 을 쓰는 역할에는 rules 를 직접 적지 않습니다. 규칙은 라벨이 붙은 다른 역할에 씁니다.
종합: 토큰이 없는 파드 만들기
cka-rbac 에 ServiceAccount no-token 을 만들되 automountServiceAccountToken: false 로 둔다. 파드 locked-down (이미지 nginx:1.27)을 만들어 serviceAccountName 을 no-token 으로 하고 파드 스펙에서도 automountServiceAccountToken: false 를 명시한다. 이 계정에는 아무 권한도 바인딩하지 않는다.
서비스어카운트와 파드 양쪽에서 끌 수 있고, 파드 쪽 설정이 우선합니다. 두 곳 모두 명시하면 의도가 분명해집니다.