본문으로 건너뛰기

CKA 개념 노트: RBAC, 사용자 인증서, kubeconfig

  • kubernetes
  • cka
  • rbac
  • csr
  • kubeconfig

기준: kubeadm 클러스터 v1.35.9 (libvirt VM 3대)에서 명령어 확인

Role, RoleBinding, ServiceAccount, kubectl auth can-i 기본은 CKAD 개념 노트: ServiceAccount, 접근 제어, SecurityContext에 정리했고, 여기서는 관리자 쪽에서 더 보는 것만 다룸.

목차

사용자는 어디에 있나

Kubernetes에는 User 객체가 없음. apiserver는 요청에 붙은 인증 정보에서 username과 group을 꺼내 쓸 뿐.

인증 방법usernamegroup
X.509 클라이언트 인증서CNO (여러 개 가능)
ServiceAccount tokensystem:serviceaccount:<ns>:<name>system:serviceaccounts, system:serviceaccounts:<ns>
OIDC 등설정한 claim설정한 claim

그래서 “사용자 jane을 만든다”는 건 CN=jane인 인증서를 클러스터 CA로 서명받는 것. RBAC binding의 subject kind: User, name: jane은 이 문자열과 맞춰질 뿐.

CSR로 사용자 인증서 발급

1. 키와 CSR 만들기

openssl genrsa -out jane.key 2048
openssl req -new -key jane.key -out jane.csr -subj "/CN=jane/O=dev-team"

2. CertificateSigningRequest 객체

apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: jane
spec:
  request: <base64 < jane.csr | tr -d "\n" 결과>
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400
  usages:
    - client auth
필드값
requestPEM CSR 파일을 base64로 한 줄로
signerName사용자 클라이언트 인증서는 kubernetes.io/kube-apiserver-client
usagesclient auth
expirationSeconds선택. 위 예는 24시간

3. 승인과 인증서 꺼내기

kubectl get csr jane
# NAME   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
# jane   kubernetes.io/kube-apiserver-client   kubernetes-admin   24h                 Pending

kubectl certificate approve jane
kubectl get csr jane            # CONDITION: Approved,Issued

kubectl get csr jane -o jsonpath='{.status.certificate}' | base64 -d > jane.crt
openssl x509 -in jane.crt -noout -subject -issuer
# subject=O = dev-team, CN = jane
# issuer=CN = kubernetes
  • 거절은 kubectl certificate deny jane
  • Approved만 되고 Issued가 안 붙으면 signer가 서명하지 않은 것. kubeadm 클러스터에서는 controller-manager가 서명함

kubeconfig

kubeconfig는 세 부분: clusters(어디로), users(누구로), contexts(둘의 조합 + 기본 namespace).

kubectl config set-credentials jane \
  --client-key=jane.key --client-certificate=jane.crt --embed-certs=true
kubectl config set-context jane --cluster=kubernetes --user=jane --namespace=dev
kubectl config get-contexts
CURRENT   NAME                          CLUSTER      AUTHINFO           NAMESPACE
          jane                          kubernetes   jane               dev
*         kubernetes-admin@kubernetes   kubernetes   kubernetes-admin
  • --embed-certs=true: 파일 경로 대신 내용을 kubeconfig에 넣음. 없으면 경로만 저장됨
  • 다른 kubeconfig 파일을 만들려면 --kubeconfig=jane.kubeconfig를 붙이고, set-cluster로 server 주소와 CA도 넣어야 함
  • kubectl config use-context jane으로 전환, 한 번만 쓰려면 kubectl --context jane ...
$ kubectl --context jane auth whoami
Username   jane
Groups     [dev-team system:authenticated]

권한을 주기 전에는 인증은 되지만 인가에서 막힘.

$ kubectl --context jane get pods
Error from server (Forbidden): pods is forbidden: User "jane" cannot list resource "pods" in API group "" in the namespace "dev"

Forbidden(403)이면 인증은 통과한 것. Unauthorized(401)이면 인증서나 token부터 문제.

Role과 ClusterRole 조합

kubectl create role pod-reader -n dev --verb=get,list,watch --resource=pods
kubectl create rolebinding jane-pod-reader -n dev --role=pod-reader --user=jane
Role 종류Binding 종류효과
RoleRoleBinding그 namespace 안에서만
ClusterRoleRoleBindingClusterRole의 규칙을 RoleBinding이 있는 namespace 안에서만
ClusterRoleClusterRoleBinding모든 namespace + 클러스터 범위 리소스
RoleClusterRoleBinding불가

ClusterRole + RoleBinding으로는 클러스터 범위 리소스(nodes, PV, namespace 등)를 줄 수 없음. 직접 해 봄.

kubectl create clusterrole node-reader --verb=get,list --resource=nodes
kubectl create rolebinding jane-nodes -n dev --clusterrole=node-reader --user=jane
kubectl --context jane get nodes
# Error from server (Forbidden): nodes is forbidden: User "jane" cannot list resource "nodes" in API group "" at the cluster scope

kubectl create clusterrolebinding jane-nodes --clusterrole=node-reader --user=jane
kubectl --context jane get nodes     # 성공

subject 종류:

kubectl create rolebinding ... --user=jane
kubectl create rolebinding ... --group=dev-team                  # 인증서 O 필드
kubectl create rolebinding ... --serviceaccount=dev:ci           # <namespace>:<name>

기본 ClusterRole

ClusterRole용도비고
cluster-admin전부ClusterRoleBinding이면 클러스터 전체, RoleBinding이면 그 namespace 전체
adminnamespace 관리자Role/RoleBinding 생성 가능. ResourceQuota와 namespace 자체는 수정 불가
edit대부분 읽기/쓰기Role, RoleBinding 수정 불가
view읽기Secret 제외

dev-team group에 view를 ClusterRoleBinding으로 줘 봄:

요청결과
get deploy -n kube-system허용
get secrets -n kube-systemForbidden (view는 Secret 제외)
get nodesForbidden (view는 namespace 리소스만)
kubectl create sa ci -n dev
kubectl create rolebinding ci-edit -n dev --clusterrole=edit --serviceaccount=dev:ci
kubectl auth can-i create deploy -n dev --as=system:serviceaccount:dev:ci        # yes
kubectl auth can-i create rolebinding -n dev --as=system:serviceaccount:dev:ci   # no

aggregated ClusterRole

aggregationRule이 있는 ClusterRole은 label selector에 맞는 다른 ClusterRole의 rules를 controller가 자동으로 합쳐 넣음. 직접 쓴 rules는 덮어써짐.

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring
aggregationRule:
  clusterRoleSelectors:
    - matchLabels:
        rbac.example.com/aggregate-to-monitoring: "true"
rules: [] # controller가 채움
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: monitoring-endpoints
  labels:
    rbac.example.com/aggregate-to-monitoring: "true"
rules:
  - apiGroups: [""]
    resources: ["services", "endpoints", "pods"]
    verbs: ["get", "list", "watch"]
$ kubectl get clusterrole monitoring -o jsonpath='{.rules}'
[{"apiGroups":[""],"resources":["services","endpoints","pods"],"verbs":["get","list","watch"]}]

기본 admin, edit, view도 이 방식. CRD 권한을 기본 role에 끼워 넣을 때 쓰는 label:

$ kubectl get clusterrole admin -o jsonpath='{.aggregationRule}'
{"clusterRoleSelectors":[{"matchLabels":{"rbac.authorization.k8s.io/aggregate-to-admin":"true"}}]}

rbac.authorization.k8s.io/aggregate-to-view: "true", aggregate-to-edit, aggregate-to-admin.

권한 확인

kubectl auth can-i list pods -n dev --as jane                     # yes
kubectl auth can-i create pods -n dev --as jane                   # no
kubectl auth can-i list pods -n dev --as bob --as-group dev-team  # group 권한만 확인
kubectl auth can-i --list -n dev --as jane
pods    []   []   [get list watch]
nodes   []   []   [get list]

--list 결과에는 기본 binding으로 모든 인증 사용자가 받는 권한(selfsubjectaccessreviews 등)과 CNI가 추가한 권한도 섞여 나옴.

binding 수정

RoleBinding의 roleRef는 바꿀 수 없음.

$ kubectl patch rolebinding jane-pod-reader -n dev --type=merge \
    -p '{"roleRef":{"apiGroup":"rbac.authorization.k8s.io","kind":"ClusterRole","name":"view"}}'
The RoleBinding "jane-pod-reader" is invalid: roleRef: Invalid value: ...: cannot change roleRef

role을 바꾸려면 binding을 지우고 다시 만듦. subjects는 수정 가능.

헷갈리는 것 비교

비교AB
인증서 CN vs Ousernamegroup
kube-apiserver-client signer vs kubelet-serving 등사용자/클라이언트 인증서. 수동 승인kubelet용. kubelet이 요청
CSR Approved vs Issued사람이 승인signer가 서명해서 status.certificate에 넣음
set-credentials vs set-contextuser 항목 (키, 인증서)cluster + user + namespace 조합
ClusterRole + RoleBinding vs + ClusterRoleBinding그 namespace 안. 클러스터 리소스 불가전체 + 클러스터 리소스
edit vs adminRBAC 객체 수정 불가namespace 안의 Role/RoleBinding 수정 가능
401 vs 403인증 실패인증 성공, 권한 없음

시험 포인트

빨리 푸는 명령어

openssl genrsa -out u.key 2048
openssl req -new -key u.key -out u.csr -subj "/CN=u/O=g"
cat u.csr | base64 | tr -d "\n"
kubectl certificate approve u
kubectl get csr u -o jsonpath='{.status.certificate}' | base64 -d > u.crt
kubectl config set-credentials u --client-key=u.key --client-certificate=u.crt --embed-certs=true
kubectl config set-context u --cluster=kubernetes --user=u

kubectl create role|clusterrole <name> --verb=... --resource=...
kubectl create rolebinding|clusterrolebinding <name> --role|--clusterrole=... --user|--group|--serviceaccount=...
kubectl auth can-i <verb> <resource> [-n ns] --as <user> [--as-group <group>]
  • CSR YAML은 공식 문서 “Certificate Signing Requests”의 normal user 예제를 복사해서 request만 바꾸면 빠름
  • --resource에 subresource는 pods/log처럼 씀

kubectl explain

kubectl explain csr.spec            # request, signerName, usages, expirationSeconds
kubectl explain clusterrole.aggregationRule
kubectl explain rolebinding.subjects

참고 문서