LabHub
배우기 러닝패스 코스

KCSA — Kubernetes Security Associate

A Cluster-Wide RBAC Audit

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

클러스터 전체의 RBAC 을 실제로 감사합니다. 와일드카드 권한과 위험 동사를 가진 ClusterRole 을 찾아내고, 서비스어카운트의 실효 권한을 kubectl auth can-i 로 측정하고, 최소 권한 Role 을 새로 만들어 그 경계가 실제로 작동하는지 증명한 뒤, 근거가 담긴 감사 리포트를 작성합니다.

왜 중요한가

RBAC 감사가 어려운 이유는 매니페스트를 읽는 것만으로는 답이 안 나오기 때문입니다. 한 주체에 여러 바인딩이 붙고, 그룹을 통해 상속되고, 기본 제공 ClusterRole 이 aggregation 으로 합쳐지기도 합니다. 머리로 계산하지 말고 apiserver 에게 물어보세요. kubectl auth can-i --list --as= 가 그 도구입니다.

와일드카드를 따로 세는 이유가 있습니다. resources: ["*"] 는 지금 있는 리소스뿐 아니라 미래에 CRD 로 추가될 리소스까지 허용합니다. "지금은 안전하다"는 반론이 통하지 않는 이유입니다.

escalate·bind·impersonate 는 특별히 위험한 메타 권한입니다. 이 동사들은 "권한을 주는 권한" 이라, 하나만 있으면 스스로를 관리자로 만들 수 있습니다. RBAC 감사에서 가장 먼저 찾아야 할 대상입니다.

마지막으로 6단계. 최소 권한이란 "필요한 것을 줬다"가 아니라 "필요하지 않은 것이 안 된다" 입니다. 읽기가 되는지만 확인하고 끝내면 반쪽입니다. 삭제가 안 되는지, 다른 네임스페이스에서 안 되는지까지 확인해야 경계를 증명한 것입니다.

단계

  1. 디렉터리 /root/kcsa-audit 와 네임스페이스 kcsa-audit 를 만들고, 그 네임스페이스에 ServiceAccount 두 개 auditorprobe 를 만듭니다. 둘 다 이 단계에서는 아무 권한도 붙이지 않습니다.
  2. 클러스터의 모든 ClusterRole 중 규칙 하나 안에서 verbsresources 가 모두 * 인 것을 찾아 이름만 한 줄에 하나씩 /root/kcsa-audit/wildcard-clusterroles.txt 에 저장합니다.
  3. kubectl auth can-i --list--as=system:serviceaccount:kcsa-audit:probe-n kcsa-audit 로 실행하고, 그 출력 전체를 가공 없이 그대로 /root/kcsa-audit/probe-can-i.txt 에 저장합니다. probe 는 이 실습이 끝날 때까지 아무 롤도 바인딩하지 않는 비교 기준이므로 나중에라도 권한을 붙이면 안 됩니다.
  4. 클러스터의 모든 ClusterRole 중 verbsescalate, bind, impersonate하나라도 문자 그대로 포함한 것을 찾아 이름만 한 줄에 하나씩 /root/kcsa-audit/dangerous-verbs.txt 에 저장합니다.
  5. system:serviceaccount:kcsa-audit:default 로 세 가지를 물어보고 결과를 /root/kcsa-audit/default-sa.txt키=값 세 줄로 저장합니다 — create-pods=(네임스페이스 kcsa-audit 에서 파드 create), get-secrets=(네임스페이스 kcsa-audit 에서 secrets get), list-nodes=(클러스터 범위 nodes list). 값은 yes/no 를 그대로 적습니다.
  6. 네임스페이스 kcsa-audit 에 Role configmap-reader 를 만듭니다 — 규칙은 정확히 하나이며 apiGroups 는 코어 그룹 하나, resources 는 configmaps 하나, verbs 는 get,list,watch 셋뿐입니다. 그리고 RoleBinding auditor-configmap-reader 로 SA auditor 에 바인딩합니다. 만든 뒤 auth can-i 로 (a) kcsa-audit 에서 configmaps list 가 되는지, (b) 같은 곳에서 delete 는 안 되는지, (c) default 네임스페이스에서는 list 도 안 되는지 확인합니다.
  7. /root/kcsa-audit/rbac-audit-report.md 를 작성합니다. 다음 네 줄이 섹션 제목으로 정확히 들어가야 합니다 — ## 와일드카드 권한, ## 위험 동사, ## 기본 서비스어카운트, ## 최소 권한 적용. 본문에 다음 다섯 단어가 언급되어야 합니다 — cluster-admin, escalate, impersonate, configmap-reader, auditor. 그리고 2단계에서 센 와일드카드 ClusterRole 개수를 wildcard-count=<숫자> 형태의 줄로 한 줄 넣습니다.

참고

감사 작업 공간 준비

디렉터리 /root/kcsa-audit 와 네임스페이스 kcsa-audit 를 만들고, 그 네임스페이스에 ServiceAccount 두 개 auditorprobe 를 만듭니다. 둘 다 이 단계에서는 아무 권한도 붙이지 않습니다.

산출물 디렉터리, 네임스페이스, 그리고 서비스어카운트 두 개를 만듭니다. 하나는 나중에 최소 권한 롤을 받을 대상이고, 다른 하나는 끝까지 아무 권한도 받지 않는 비교 기준입니다. 기준이 없으면 '권한이 늘었다'를 말할 수 없습니다.

와일드카드 권한 ClusterRole 찾기

클러스터의 모든 ClusterRole 중 규칙 하나 안에서 verbsresources 가 모두 * 인 것을 찾아 이름만 한 줄에 하나씩 /root/kcsa-audit/wildcard-clusterroles.txt 에 저장합니다.

규칙 하나 안에서 verbs 와 resources 가 모두 * 인 경우를 찾습니다. 규칙은 배열이고 ClusterRole 하나에 여러 개 있을 수 있으니, 어느 하나라도 조건을 만족하면 그 역할을 목록에 넣습니다. jq 의 select 와 any 를 조합하면 한 줄로 됩니다.

권한 없는 서비스어카운트의 기준선 뜨기

kubectl auth can-i --list--as=system:serviceaccount:kcsa-audit:probe-n kcsa-audit 로 실행하고, 그 출력 전체를 가공 없이 그대로 /root/kcsa-audit/probe-can-i.txt 에 저장합니다. probe 는 이 실습이 끝날 때까지 아무 롤도 바인딩하지 않는 비교 기준이므로 나중에라도 권한을 붙이면 안 됩니다.

auth can-i 에는 개별 질문 말고 전체 목록을 뽑는 옵션이 있습니다. 대상은 --as 로 지정하고, 네임스페이스 범위 권한도 보려면 -n 을 함께 줘야 합니다. 출력을 grep 이나 정렬로 가공하지 말고 그대로 저장하세요. 여기 나오는 몇 줄이 '아무 권한도 없는 계정'의 기준선이며, 이 계정에는 끝까지 아무 롤도 붙이면 안 됩니다.

위험 동사 보유 ClusterRole 탐지

클러스터의 모든 ClusterRole 중 verbsescalate, bind, impersonate하나라도 문자 그대로 포함한 것을 찾아 이름만 한 줄에 하나씩 /root/kcsa-audit/dangerous-verbs.txt 에 저장합니다.

세 동사가 각각 무엇을 가능하게 하는지 떠올려 보면 왜 함께 묶어 보는지 이해됩니다. 여기서는 동사가 문자 그대로 적힌 것만 셉니다 — 와일드카드는 이미 앞 단계에서 따로 집계했습니다.

기본 서비스어카운트가 무엇을 할 수 있나

system:serviceaccount:kcsa-audit:default 로 세 가지를 물어보고 결과를 /root/kcsa-audit/default-sa.txt키=값 세 줄로 저장합니다 — create-pods=(네임스페이스 kcsa-audit 에서 파드 create), get-secrets=(네임스페이스 kcsa-audit 에서 secrets get), list-nodes=(클러스터 범위 nodes list). 값은 yes/no 를 그대로 적습니다.

모든 네임스페이스에는 default 서비스어카운트가 자동으로 있고, 파드가 SA 를 지정하지 않으면 이것을 씁니다. 이 계정이 무엇을 할 수 있는지 직접 물어보고 답을 그대로 옮기세요. 클러스터 범위 리소스를 물을 때는 네임스페이스 옵션이 필요 없습니다.

최소 권한 Role 만들고 경계 증명하기

네임스페이스 kcsa-audit 에 Role configmap-reader 를 만듭니다 — 규칙은 정확히 하나이며 apiGroups 는 코어 그룹 하나, resources 는 configmaps 하나, verbs 는 get,list,watch 셋뿐입니다. 그리고 RoleBinding auditor-configmap-reader 로 SA auditor 에 바인딩합니다. 만든 뒤 auth can-i 로 (a) kcsa-audit 에서 configmaps list 가 되는지, (b) 같은 곳에서 delete 는 안 되는지, (c) default 네임스페이스에서는 list 도 안 되는지 확인합니다.

규칙 하나에 필요한 것만 담습니다. 코어 API 그룹은 이름이 빈 문자열입니다. 만든 뒤에는 원하는 것이 되는지뿐 아니라 원하지 않는 것이 안 되는지도 확인해야 최소 권한이라고 말할 수 있습니다 — 특히 다른 네임스페이스에서 안 되는지.

감사 리포트로 묶기

/root/kcsa-audit/rbac-audit-report.md 를 작성합니다. 다음 네 줄이 섹션 제목으로 정확히 들어가야 합니다 — ## 와일드카드 권한, ## 위험 동사, ## 기본 서비스어카운트, ## 최소 권한 적용. 본문에 다음 다섯 단어가 언급되어야 합니다 — cluster-admin, escalate, impersonate, configmap-reader, auditor. 그리고 2단계에서 센 와일드카드 ClusterRole 개수를 wildcard-count=<숫자> 형태의 줄로 한 줄 넣습니다.

앞 단계들의 산출물을 근거로 하나의 문서를 만듭니다. 섹션 제목은 지시된 형태 그대로여야 하고, 2단계에서 센 개수를 숫자로 적는 줄이 하나 필요합니다. 그 숫자는 채점 시점에 다시 계산해 대조합니다.