[쿠버네티스] RBAC 기반 ServiceAccount

600g (Kim Dong Geun)·2021년 7월 22일
0

쿠버네티스 10장

쿠버네티스는 보안측면에서도 다양한 기능 제공

  • RBAC를 기반으로 하는 서비스 어카운트

    서비스 어카운트 : 사용자 또는 어플리케이션 하나에 해당

    RBAC(Role based Access Control) : 특정명령을 실행할 수 있는 권한 (서비스를 읽을 권리, 포드를 생성할 권리)

  • 지금까지 사용했던 kubectl 명령어는 최상위 권한에 해당

    • 실제로 cat ~/.kube/config를 보면 kubectl 권한 등이 들어있음.

    • 그래서 여러명의 사용자가 쿠버네티스 접근 -> kubectl을 제공하는 것은 옳지않음.

Kube - api server 컴포넌트

우리가 실제로 kubectl 명령어를 사용하면 내부구현은 다음과 같은 일이 일어남.

  • Authentication : 해당 클라이언트가 쿠버네티스의 사용자가 맞는지 검증
  • Authorization : 해당 사용자가 해당 기능을 실행할 권할을 가지는지

Auth를 구현하기 위해서는 Service Account 방법 외에도 Oauth, 인증서 방법등이 있다고함

서비스 어카운트와 롤

  • 서비스 어카운트는 체계적으로 권한을 관리하기 위한 오브젝트

  • 네임 스페이스에 속하는 오브젝트

서비스 어카운트 생성

kubectl create sa {계정명}

# or

kubectl create serviceaccount {계정명}
kubectl get sa {계정명}

# or

kubectl get serviceaccount {계정명}

서비스 어카운트로 명령실행

### ex
kubectl get services --as system:serviceaccount:{네임스페이스}:{계정명}
  • 서비스 어카운트는 부여된 Role이외의 명령어는 실행할 수 없다.

  • 쿠버네티스에서 권한을 부여하는 방법은 크게 2가지

    1. 롤 (Role)

      네임스페이스에 속하는 오브젝트로 다른 네임스페이스에 속하는 오브젝트들에 대한 권한을 정의

    2. 클러스터 롤 (Cluster Role)

      클러스터 단위의 권한을 정의

      네임스페이스에 속하지 않는 전역적인 쿠버네티스 오브젝트

롤과 클러스터 롤은 모두 쿠버네티스 오브젝트

따라서

kubectl get role
No resources found.

# 쿠버네티스 현재 네임스페이스에 속하는 권한 출력

kubectl get clusterrole

#전역적이므로, 클러스터 자체에 존재하는 모든 클러스터 롤의 목록을 출력

롤 적용해보기

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: service-reader
rules:
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get","list"]
kubectl apply -f service-reader-role.yaml

롤을 적용했다고 해서, 서비스 어카운트에 해당 권한이 부여되는 것은 아님.

롤 바인딩 하기

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: service-reader-rolebinding
  namespace: default
subjects:
- kind: ServiceAccount    # 권한을 부여할 대상이 ServiceAccount
  name: ehdrms2034        # ehdrms2034이라는 이름의 서비스 어카운트에 권한을 부여
  namespace: default
roleRef:
  kind: Role              # Role에 정의된 권한을 부여
  name: service-reader    # service-role라는 이름의 Role을 대상에 연결
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f rolebiding-service-reader.yaml

확인

kubectl get services --as system:serviceaccount:default:ehdrms2034

### 부여받지 않은 권한 사용하면 안됨
kubectl get deployment --as system:serviceaccount:default:ehdrms2034

클러스터 롤

클러스터 롤은 네임스페이스에 한정되지 않은 오브젝트에 권한을 부여하기 위해 사용됨

기본적으로 롤은 네임스페이스에 한정된 오브젝트에 권한을 부여하기 위해 사용

#node는 namespace에 한정되지 않은 오브젝트인데, role로 권한을 부여받은 사용자가 명령을 수행하면 오류가남.
kubectl get nodes --as system:serviceaccount:default:ehdrms2034

이럴 경우는 클러스터 롤을 사용함.

클러스터 롤 적용

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  namespace: default # namespace에 한정되지 않는다 했는데 왜 부여하는지..?
  name: nodes-reader
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list"]
kubectl apply -f nodes-reader-clusterrole.yaml


#클러스터 롤 권한 확인하기
kubectl describe clusterrole {클러스터 롤 네임}

#ex kubectl describe clusterrole nodes-reader

클러스터 롤 역시 바인딩이 필요함

클러스터 롤 바인딩

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: nodes-cluster-clusterrolebinding
  namespace: default
subjects:
- kind: ServiceAccount
  name: ehdrms2034
  namespace: default
roleRef:
  kind: ClusterRole
  name: nodes-reader
  apiGroup: rbac.authorization.k8s.io
kubectl apply -f clusterrolebinding-nodes-reader.yaml
#### 권한 부여 확인해보기
kubectl get nodes --as system:serviceaccount:default:ehdrms2034

쿠버네티스 API 서버에 접근

  • 일반적으로 사용자가 kubectl 을 사용하여 쿠버네티스를 조작
  • kubectl은 일종의 cli 형태의 클라이언트로, 실제로는 쿠버네티스 api 서버에 접근하여 명령어 수행
  • 실제로 어플리케이션에 쿠버네티스에 접근하려면, kubectl이 아닌 쿠버네티스 api에 요청을 수행

쿠버네티스 api 서버에 요청보내기

curl {쿠버네티스 마스터 IP}:6443/apis -k

그런데 403 에러가 발생

System:anoymous에 대한 인증 실패가 뜸.

"내가 서비스 어카운트 XX이다" 라는 권한 정보를 같이 보내줘야하는데, 해당 인증 정보는 Secret을 가지고 있습니다.

시크릿 확인하기

kubectl get secrets

서비스 어카운트 생성할때, 시크릿도 같이 생성됨.

해당 서비스 어카운트와 연결된 시크릿을 확인하는 방법은 다음과 같다.

kubectl describe sa {서비스 어카운트 명}


# Moutable secrets: ~~
# Tokens : ~
kubectl describe secret {시크릿명}

# ca.crt, namespace, token

ca.crt : 쿠버네티스 클러스터의 공개 인증서 저장

namespace : 해당 서비스 어카운트가 존재하는 네임스페이스 저장

token: kube - api server에 인증할 jwt 인증에 사용. 일반적으로 base 64 인코딩으로 저장이 되어있음.

따라서 token을 가지고 api server에 요청을 수행하려면 다음과 같이 수행합니다.

export decoded_token=$(kubectl get secret {secret-name} -o jsonpath='{.data.token}' | base64 -d)
curl {마스터 IP}:6443/apis --header "Authorization: Bearer. $decoded_token" -k

클러스터 내부에서 kubernetes로 접근

  • 이전의 nginx 인그레스 컨트롤러가 인그레스의 생성을 동적으로 감지해서 nginx 라우팅 규칙을 변경해줌

    • 쿠버네티스 API에 접근해서 watch api를 걸어두는 동작
  • 위 동작은 어떻게 수행을 하고 있었던 것일까

kubectl get svc

를 해보면 default로 생성이 되어있는 kubernetes 서비스가 확인되어있는 것을 볼 수 있음.

  • 쿠버네티스는 포드를 생성할때 자동으로 서비스 어카운트의 시크릿을 포드 내부에 배치해두며 확인 방법은 아래와 같음
kubectl describe pods {포드명}

### Mounts: 확인
  • 혹은 직접 지정할 수 있는데 deployment를 생성할때
spec:
  serviceAccountName: {sa 명}

유저와 그룹의 개념

쿠버네티스는 서비스 어카운트 외에도 유저와 그룹의 개념이 존재.

  • 유저(User) : 실제 사용자를 뜻함 (서비스 어카운트도 유저의 종류중 하나로 속함)
  • 그룹(Group): 여러 유저들을 모아 놓은 집함을 뜻함.

따라서 롤 바인딩을 정의할 때 ServiceAccount 대신 User나 Group을 사용할 수 도 있음.

...
subjects:
- kind: User
  name: ehdrms2034
...

## or

subjects:
- kind: Group
  name: 그룹명

앞서 나왔던

kubectl get services --as system:serviceaccount:default:ehdrms2034

에서

system:serviceaccount가 그룹명이라고 볼수 있고

system:serviceaccount:default:ehdrms2034 가 유저명이라고 볼 수 있음.

profile
수동적인 과신과 행운이 아닌, 능동적인 노력과 치열함

0개의 댓글