[Kubernetes] 인증(RBAC)

RBAC: Role Based Access Control

공식문서:https://kubernetes.io/docs/reference/access-authn-authz/rbac/

역할 기반 액세스 제어(RBAC)는 조직 내 개별 사용자의 역할에 따라 컴퓨터 또는 네트워크 리소스에 대한 액세스를 규제하는 방법이다.

RBAC 권한 부여는 다음을 사용한다.rbac.authorization.k8s.io API 그룹Kubernetes API를 통해 정책을 동적으로 구성할 수 있도록 하여 권한 부여 결정을 추진한다. AWS 에서의 IAM 정채과 역할이라고 생각하면 된다. 

RBAC를 활성화하려면 다음을 작업을 거쳐야 한다. 

kube-apiserver --authorization-mode=Example,RBAC --other-options --more-options

사용자 유형(User Types)

ServiceAccount (SA)

Kubernetes 내부에서 실행되는 애플리케이션이나 서비스가 클러스터 API에 접근할 때 사용

사용자가 사용하지 않고 Pod가 사용하는 계정이라고 생각하면 된다. 

Normal User (외부 사용자)

클러스터 외부에서 접근하는 일반 사용자를 의미하며 Kubernetes는 직접 생성하지 않는다. (x509 인증서, OIDC 등으로 관리)

kubectl이나 외부 애플리케이션을 통해 API에 접근한다. 

API 객체

RBAC API는 Role , ClusterRole , RoleBinding  ClusterRoleBinding 의 네 가지 Kubernetes 객체를 선언한다 . RBAC를 설명하거나 수정할 수 있다.

Role

특정 네임스페이스 내 리소스에 대한 권한 정의한다. (ex: 특정 네임스페이스 내 pods, services에 대한 읽기 권한 부여)

ClusterRole

클러스터 전체의 모든 네임스페이스에 대한 권한을 정의한다. 

  • 네임스페이스 리소스에 대한 권한을 정의하고 개별 네임스페이스 내에서 액세스 권한을 부여받는다. 
  • 네임스페이스 리소스에 대한 권한을 정의하고 모든 네임스페이스에서 액세스 권한을 부여받는다. 
  • 클러스터 범위 리소스에 대한 권한 정의

네임스페이스 내에서 역할을 정의하려면 Role을 사용하고, 클러스터 전체에서 역할을 정의하려면 ClusterRole을 사용한다. 

RoleBinding

Role을 특정 네임스페이스 내 사용자/SA에 연결 (ex: pod-reader 역할을 readonly-user 사용자에게 부여) 

ClusterRoleBinding

ClusterRole을 모든 네임스페이스의 사용자/SA에 연결

Role 예

다음은 읽기 액세스 권한을 부여하는 데 사용할 수 있는 "기본" 네임스페이스의 역할 예이다. 

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRole 예제

ClusterRole은 Role과 동일한 권한을 부여하는 데 사용할 수 있다. ClusterRole은 클러스터 범위이므로 다음에 대한 액세스 권한을 부여하는 데 사용할 수도 있다.

  • 클러스터 범위 리소스(예:노드)
  • 비 리소스 엔드포인트(예: /healthz)
  • 모든 네임스페이스에 걸쳐 네임스페이스 리소스(Pod 등)
  • 예를 들어 ClusterRole을 사용하면 특정 사용자가 다음을 실행할 수 있다. kubectl get pods --all-namespaces

다음은 읽기 액세스 권한을 부여하는 데 사용할 수 있는 ClusterRole의 예이다. 특정 네임스페이스 또는 모든 네임스페이스(바인딩 방식에 따라 다름). 

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: secret-reader
rules:
- apiGroups: [""]
  #
  # at the HTTP level, the name of the resource for accessing Secret
  # objects is "secrets"
  resources: ["secrets"]
  verbs: ["get", "watch", "list"]

RoleBinding 예제

다음은 "default" 네임스페이스 내에서 사용자 "jane"에게 "pod-reader" 역할을 부여하는 RoleBinding의 예이다. 이를 통해 "jane"은 "default" 네임스페이스에서 파드를 읽을 수 있다. 

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
  name: jane # "name" is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # "roleRef" specifies the binding to a Role / ClusterRole
  kind: Role #this must be Role or ClusterRole
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

RoleBinding은 ClusterRole을 참조하여 해당 ClusterRole에 정의된 권한을 RoleBinding의 네임스페이스 내부 리소스에 부여할 수도 있다. 이러한 종류의 참조를 통해 클러스터 전체에서 공통 역할 세트를 정의한 다음 여러 네임스페이스 내에서 재사용할 수 있다.

예를 들어, 다음 RoleBinding이 ClusterRole을 참조하더라도 "dave"(주체, 대소문자 구분)는 "development" 네임스페이스의 Secrets만 읽을 수 있다. 그 이유는 RoleBinding의 네임스페이스(메타데이터 내)가 "development"이기 때문이다. 

apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "dave" to read secrets in the "development" namespace.
# You need to already have a ClusterRole named "secret-reader".
kind: RoleBinding
metadata:
  name: read-secrets
  #
  # The namespace of the RoleBinding determines where the permissions are granted.
  # This only grants permissions within the "development" namespace.
  namespace: development
subjects:
- kind: User
  name: dave # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding 예제

클러스터 전체에 권한을 부여하려면 ClusterRoleBinding을 사용할 수 있다. 다음 ClusterRoleBinding은 "manager" 그룹의 모든 사용자가 모든 네임스페이스의 비밀을 읽을 수 있도록 허용한다. 

apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager # Name is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

ServiceAccount 생성

kubectl create sa myuser1
serviceaccount/myuser1 created
  • ServiceAccount 생성 후 토큰이 자동 생성됨.
  • ServiceAccount는 네임스페이스 기본 토큰과 연결됨.
kubectl describe sa myuser1
Name:                myuser1
Namespace:           default
Labels:              <none>
Annotations:         <none>
Image pull secrets:  <none>
Mountable secrets:   myuser1-token-xxxxx
Tokens:              myuser1-token-xxxxx
Events:              <none>

Kubernetes 사용자 생성: x509 인증서 기반

1. Private Key 생성

먼저, 사용자 인증을 위한 Private Key를 생성한다. 이 키는 클라이언트가 인증서를 기반으로 Kubernetes API 서버와 통신하는 데 사용된다.

openssl genrsa -out newuser.key 2048
  • newuser.key: 생성된 Private Key 파일이다. 

2. x509 인증서 요청 (CSR) 생성

CSR (Certificate Signing Request)을 생성하여 Kubernetes에 사용자를 등록한다. Common Name (CN) 필드는 사용자 이름으로 설정해야 하며, 이는 Kubeconfig의 사용자 이름과 일치해야 한다.

openssl req -new -key newuser.key -out newuser.csr -subj "/CN=newuser"
  • /CN=newuser: Common Name에 사용자 이름 newuser를 설정한다. 
  • newuser.csr: 결과물로 생성된 CSR 파일이다. 

3. CSR 내용을 Base64로 인코딩

Kubernetes CSR 리소스에 등록하기 위해 CSR 결과물 내용을 Base64로 인코딩한다.

cat newuser.csr | base64 | tr -d "\\n"
  • 결과 문자열은 YAML 파일에 입력해야한다. 

4. Kubernetes CSR 리소스 생성

CSR을 Kubernetes에 등록하기 위해 YAML 파일을 작성한다. 

# csr.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: newuser-csr
spec:
  request: LS0tLS1CRUdJTiB... # Base64로 인코딩된 CSR 문자열
  signerName: kubernetes.io/kube-apiserver-client
  usages:
    - client auth

YAML 파일 적용

kubectl create -f csr.yaml

5. CSR 승인 및 인증서 발급

CSR의 상태를 확인한다.

kubectl get csr
  • 상태: Pending

CSR을 승인한다. 

kubectl certificate approve newuser-csr

CSR이 승인되면 상태가 Approved, Issued로 변경된다. 

kubectl get csr

발급된 인증서를 파일로 저장한다. 

kubectl get csr newuser-csr -o jsonpath='{.status.certificate}' | base64 -d > newuser.crt

6. 인증서 내용 확인

발급된 인증서를 검증한다. 

openssl x509 -in newuser.crt -text -noout

7. Kubeconfig에 사용자 추가

Kubeconfig 파일에 새 사용자를 추가한다.

kubectl config set-credentials newuser --client-certificate=newuser.crt --client-key=newuser.key --embed-certs=true

8. Kubeconfig에 컨텍스트 생성

새 사용자와 클러스터를 연결하는 컨텍스트를 생성한다.

kubectl config set-context newuser-context --cluster=cluster.local --user=newuser --namespace=default 
kubectl config use-context newuser-context

컨텍스트 확인

kubectl config get-contexts

9. 사용자에 권한 부여

새 사용자가 Kubernetes 리소스에 접근할 수 있도록 권한을 부여한다. ClusterRoleBinding을 생성하여 뷰(view) 권한을 할당한다.

# newuser-view-crb.yml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: newuser-view-crb
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: view
subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: newuser
YAML 파일 적용
kubectl create -f newuser-view-crb.yml

10. 권한 확인 및 테스트

새 컨텍스트로 전환 후 리소스에 접근 가능한지 확인한다.

kubectl config use-context newuser-context
kubectl get pods
 

특정 리소스에 권한이 없으면 다음과 같은 오류 메시지가 출력된다. 

Error from server (Forbidden): User "newuser" cannot create resource "pods" in API group "" in the namespace "default"

kubectl auth can-i: 사용자의 권한을 빠르게 확인할 수 있는 명령어이다. 

'kubernetes' 카테고리의 다른 글

[kubernetes] Version Upgrade  (0) 2024.12.11
[Kubernetes] 고가용성 토폴로지에 대한 옵션  (0) 2024.12.11
[kubernetes] Pod AutoScaling(HPA)  (0) 2024.12.10
[Kubernetes] StatefulSet  (0) 2024.12.10
[kubernetes] deployment  (0) 2024.12.10