본문 바로가기
Infra & Cloud/DevOps

[Kubernetes] Authentication/Authentication(인증/인가) 프로세스 및 User/Role 생성(User, CSR, RBAC, RoleBinding)

by newstellar 2022. 12. 13.
반응형

 

1. 쿠버네티스에서의 User 개념

 

  쿠버네티스에서는 User(human)와 ServiceAccount(machine) 두 종류의 사용자가 존재합니다. User에는 클러스터 관리자 및 사용자(일반 개발자)가 있으며, ServiceAccount는 Prometheus, Jenkins 등의 Pod 단위로 동작하는 컨테이너들이 API를 사용하기 위해 권한을 부여받은 machine을 뜻합니다. 쿠버네티스에는 우리가 일반적으로 이해하고 있는 User Account과 매칭되는 개념의 객체가 존재하지 않습니다. 즉, 일반적인 방식인 API Call을 통해서는 클러스터에 '지금 사용자가입하니깐 DB 같은데 등록해놔라~'라고 등록할 수 없다는 말입니다.

  대신, 클러스터의 인증 기관(CA)이 서명한 유효한 인증서를 제시하는 객체를 인증된 "User"로 간주합니다. 아래부터 사용하는 사용자는 이 문장에서 쓰인 맥락으로 통일하도록 하겠습니다. 이러한 방식에서 쿠버네티스는 인증서의 '제목'의 CommonName 필드에서 사용자 이름을 명시해둡니다(ex. /CN=Bob). CN으로 기록된 사용자는 역할 기반 액세스 제어(RBAC)를 통해 쿠버네티스 리소스(Pod, Secret, Deployment 등)에 대해 특정 작업(create, get, list, delete 등)을 수행할 권한이 있는지 여부를 결정합니다.

https://passwd.tistory.com/entry/k8s-User-생성

 

  User와 달리 ServiceAccount(SA)는 쿠버네티스 API에 의해 관리되는데요, SA는 특정 namespace에 종속되고 api-server에 의해 자동으로 또는 관리자/개발자의 API Call을 통해 수동으로 생성됩니다. 또한, Secret API Object에 저장된 자격 증명(certificates) 세트에 연결되어 클러스터 내 프로세스가 쿠버네티스 API와 소통이 가능하게끔 Pod에 마운트됩니다.

 

  API 요청은 User, SA, 또는 Anonymous로부터 받을 수 있습니다. kubectl 명령어를 타이핑하는 입력하는 인간 사용자, Node의 kubelet, Control-plane의 컴포넌트 등 클러스터 내부/외부의 모든 프로세스가 API 서버에 요청할 때마다 특정 권한을 받기 위한 인가(Authentication) 이전에 인증(Authorization)을 받거나 그렇지 못하여 Anonymous한 사용자로 남아 API 요청이 거부됩니다. 

Client가 Server로 API 요청 Call을 날릴 때 적절한 Bearer Token을 header에 추가해주지 않으면 반환되는 status가 401 Unauthorizaed 에러입니다.

 

  그렇다면 인증은 어떠한 방식으로 이뤄질까요? User 및 ServiceAccount로부터 받은 API는 아래 다섯 가지 방식으로 인증할 수 있습니다. 

1. Service Account Token
2. 정적 Token
3. Password file
4. X.509 Client 인증서
5. OpenID Connect

  위 가운데서 4번인 X.509 Client 인증서 방식은 비대칭 암호화 기술을 이용한 공개키 기반의 인증 표준으로서, 아래 사진처럼 Alice가 Bob에게 데이터를 전송할 때 Alice는 자신의 private key로 암호화를 하고 Bob은 Alice로부터 건네 받은 public key로 복호화를 하는 방식입니다. 오늘은 이 비대칭 암호화 기술을 중심으로 설명해보고자 합니다.

 

https://coffeewhale.com/kubernetes/authentication/x509/2020/05/02/auth01/

 

 

2. Authorization(인증) / Authentication(인가)

 

  쿠버네티스 클러스터에서 인증을 얘기하기 전에 빼놓을 수 없는 개념이 CertificateSigningRequest(CSR)입니다. 인증서 발급을 위해 필요한 정보를 저장하고 있는 인증서로서, 신청 형식 데이터 공개 키와 인증서 적용되는 도메인에 대한 정보 등이 포함됩니다. 쿠버네티스에서는 CSR을 API Object로 관리할 수 있고, 이를 통해서 Cluster가 이용중인 Private Root CA으로부터 인증서를 발급받는 기능을 제공합니다. Kubernetes CSR 인증서를 발급받는 과정은 다음과 같습니다.

1. 인증서의 Private Key 생성
2. 생성한 인증서의 Private Key를 이용하여 csr 파일 생성
3. 생성한 CSR 파일의 내용을 base64로 Encoding한 문자열을 이용하여 Kubernetes의 CertificateSigningRequest Manifest 작성 및 인증서 발급 요청
4. 인증서 발급 요청 수락

 

  (1) 쿠버네티스 관리자 입장의 CSR 발급

 

  클러스터 내 인증 작업을 진행하려면 우선 CSR(CertificateSigningRequests)를 생성/승인/사인할 관리자 ClusterRole이 필요합니다. 아래 csr-creator, csr-approver, csr-signer로 명명한 세 ClusterRole의 .yaml 파일을 살펴보면 됩니다.

 

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: csr-creator
rules:
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests
  verbs:
  - create
  - get
  - list
  - watch

 

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: csr-approver
rules:
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests/approval
  verbs:
  - update
- apiGroups:
  - certificates.k8s.io
  resources:
  - signers
  resourceNames:
  - example.com/my-signer-name 
  # example.com/* can be used to authorize for all signers in the 'example.com' domain
  verbs:
  - approve

 

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: csr-signer
rules:
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - certificates.k8s.io
  resources:
  - certificatesigningrequests/status
  verbs:
  - update
- apiGroups:
  - certificates.k8s.io
  resources:
  - signers
  resourceNames:
  - example.com/my-signer-name 
  # example.com/* can be used to authorize for all signers in the 'example.com' domain
  verbs:
  - sign

 

 

  (2) 쿠버네티스 사용자(개발자) 입장의 CSR 및 Role 생성

 

  A. 개인 키(Private key) 생성

  marcel 이라는 이름을 지닌 user의 .key.csr 파일을 만들어 줍니다. 이때 openssl genrsa 명령어 마지막 인자인 2048은 개인키의 사이즈이며, 반드시 명령어 마지막에 위치합니다. (default: 512)

openssl genrsa -out marcel.key 2048
openssl req -new -key marcel.key -out marcel.csr -subj "/CN=marcel"

 

 

 

  B. CertificateSigningRequest (API 오브젝트) 생성

  단계 A에서 생성한 .csr 파일을 base64 인코딩한 문자열을 이용하여 Manifest .yaml을 작성하고, 인증서 발급을 요청합니다. 그리고 kubectl apply 명령어를 통해 CSR API 오브젝트를 만들어 줍니다. 이때, spec.request에는 base64 인코딩 문자열을 넣어줍니다.

cat marcel.csr | base64 | tr -d "\n"
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: myuser
spec:
  request: [CSR base64 Decoded String]
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400  # one day
  usages:
  - client auth
EOF

 

 

  C. CSR 승인 (인증서 발급 승인)

 

  단계 B에서 만든 CSR를 조회하면, 아직 인증서가 승인되어 있지 않아 Pending 상태로 나타납니다. 인증서 발급을 승인해줍니다. (Pending -> Approved,Issued)

kubectl get csr

NAME          AGE   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
marcel        44s   kubernetes.io/kube-apiserver-client   kubernetes-admin   <none>              Pending
kubectl certificate approve marcel

certificatesigningrequest.certificates.k8s.io/marcel approved
kubectl get csr

NAME          AGE    SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
marcel	      108s   kubernetes.io/kube-apiserver-client   kubernetes-admin   <none>              Approved,Issued

 

 

  D-1. crt 파일 및 Role / RoleBinding 생성

 

  .kube/config 파일에 권한 자격을 가진 User를 만들기 위해서는 제일 처음에 생성한 marcel.key와 marcel.crt 파일이 필요합니다. 따라서 CSR API 오브젝트를 정의한 json에서 certificate를 base64 디코딩하여 저장하는 방식으로 marcel.crt 파일을 만들어줍니다.

kubectl get csr marcel -o jsonpath='{.status.certificate}'| base64 -d > marcel.crt
kubectl config set-credentials marcel \ 
  --client-key=marcel.key \
  --client-certificate=marcel.crt \
  --embed-certs=true

User "app-manager" set.

  위처럼 set-credentials 명령어로 자격 증명을 생성하면, .kube/config 파일에는 users 항목 아래 user인 marcel이 추가됩니다.

kubectl config view

...
users:
- name: marcel
  user:
    client-certificate-data: REDACTED
    client-key-data: REDACTED
- name: hk8s-admin
...

  생성된 user(marcel)과 clustercontext(kubernetes; 기본)를 설정해줍니다. (set-context)

kubectl config set-context app-manager --cluster=kubernetes --user=marcel

Context "marcel" created.
kubectl config view

...
contexts:
- context:
    cluster: kubernetes
    user: marcel
  name: marcel
- context:
...

 

 

  D-2. (Cluster)Role / RoleBinding 생성

 

  D-1 단계에서 set-credentials, set-context로 .kube/config 파일을 수정하는 것과 병렬적으로, C 단계에서 만들어놓은 CSR API 오브젝트에 Role을 부여하는 RoleBinding 단계는 D-1 이전에 수행해도 무방합니다. 아래 예제는 ClusterRole과 ClusterRoleBinding을 만드는 작업인데요, Role / RoleBinding과의 차이는 namespace의 여부입니다. ClusterRole은 namespace에 상관 없이 전체 클러스터 내 리소스에 대한 접근 권한을 정의할 수 있습니다.

 

  먼저 marcel-role이라는 이름의 ClusterRole을 만들어 봅시다.

kubectl create clusterrole marcel-role \
  --verb=create,list,get,update,delete \
  --resource=deployment,pod,service

clusterrole.rbac.authorization.k8s.io/marcel-role created

 

kubectl get clusterrole marcel-role

NAME          CREATED AT
marcel-role   2022-07-11T05:01:47Z

 

kubectl describe clusterrole marcel-role

Name:         marcel-role
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources         Non-Resource URLs  Resource Names  Verbs
  ---------         -----------------  --------------  -----
  pods              []                 []              [create list get update delete]
  services          []                 []              [create list get update delete]
  deployments.apps  []                 []              [create list get update delete]

 

  이제, ClusterRole(marcel-role)을 CSR(API 오브젝트)에 부여하기 위한 ClusterRoleBinding(marcel-role-binding)을 생성하여 실습을 마무리합니다.

kubectl create clusterrolebinding marcel-role-binding \
  --clusterrole=marcel-role \
  --user=marcel

clusterrolebinding.rbac.authorization.k8s.io/marcel-role-binding created

 

kubectl get clusterrolebindings marcel-role-binding

NAME                   ROLE                     AGE
marcel-role-binding    ClusterRole/app-access   28s

 

kubectl describe clusterrolebindings marcel-role-binding

Name:         marcel-role-binding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  marcel-role
Subjects:
  Kind  Name    Namespace
  ----  ----    ---------
  User  marcel

 


 

 

 

[Kubernetes] Volume: Pod의 Container 데이터는 어떻게 저장될까? (Volume, PersistentVolume, PersistentVolumeClaim)

1. Volume Kubernetes(쿠버네티스) 환경에서 Container(컨테이너)는 Pod(파드)에 감싸져서 동작합니다. 이때 Container에서 만들어진 데이터는 Docker(도커) 파일 시스템으로서 컨테이너 이미지에서만 제공됩

newstellar.tistory.com

 

 

[Kubernetes] StaticPod: Master Node(Control Plane)의 Pod를 삭제하면 어떻게 될까? (Container Runtime, Containerd)

시작하며 일반 개발자가 아닌, 관리자의 입장에서는 Kubernetes 클러스터의 노드에서 Pod가 실행될 때 발생하는 에러들에 대해서 알아야 합니다. (만약 CKAD 수준의 쿠버네티스 이해 및 사용 능력이

newstellar.tistory.com

 

[Kubernetes] Volume: Pod의 Container 데이터는 어떻게 저장될까? (Volume, PersistentVolume, PersistentVolumeClaim)

1. Volume Kubernetes(쿠버네티스) 환경에서 Container(컨테이너)는 Pod(파드)에 감싸져서 동작합니다. 이때 Container에서 만들어진 데이터는 Docker(도커) 파일 시스템으로서 컨테이너 이미지에서만 제공됩

newstellar.tistory.com

 

 

[Kubernetes] NetworkPolicy를 통해 Pod끼리의 트래픽을 통제해보자. (Ingress/Egress, from/to, namespaceSelector, pod

[ NetworkPolicy ] 1. Ingress vs Egress 네트워크 트래픽은 외부로부터 유입되는 Ingress(inbound)와 내부로부터 외부로 나가는 Egress(outbound)로 구분됩니다. 우리가 공부하고 있는 쿠버네티스는 기본적으로 non-

newstellar.tistory.com

 

[Kubernetes] CKA(Certified Kubernetes Administration) 자격증 접수 방법/예약/출제 범위/할인바우처 (+CKAD, CKS 

CNCF(Cloud Native Computing Foundation) 재단에서 주관하는 CKA(관리), CKAD(개발), CKS(보안) 세 자격증 가운데, 가장 대표적인 CKA 자격증에 대해 알아봅니다. 접수 및 시험 예약 방법, 추천하는 강좌 그리고 

newstellar.tistory.com

 

반응형

댓글