본문 바로가기
kubernetes

[kubernetes] 쿠버네티스 인증, 인가(rbac)

by devjh 2021. 7. 14.
반응형

1. 쿠버네티스 인증이란?

쿠버네티스 사용자가 맞는지 확인하는 작업입니다.

 

쿠버네티스 마스터노드에는 api서버가 있으며 보통 쿠버네티스 클라이언트인 kubectl을 이용하여 요청을 보냅니다.

이는 .kube/config파일에 인증작업이 되어있어서 가능합니다.

 

그러나 직접 쿠버네티스 api를 통해 클러스터의 리소스들을 관리하고싶다면 쿠버네티스의 인증방식을 알아야 합니다.

특히 operator등을 pod으로 띄워서 어플리케이션으로 코드로 내 클러스터를 관리, 운영 하고싶다면 쿠버네티스 api서버의 인증방식을 알아야합니다.

 

2. 토큰을 이용하여 http request를 날려 401에러와 403에러 확인

(1). 토큰확인하기

아래의 명령어를 통해 default serviceaccount의 token을 확인할수 있으며

http header에 넣어 api서버에 접근할 수 있습니다.

$ kubectl describe secret $(kubectl get secrets | grep default | cut -f1 -d ' ') | grep -E '^token' | cut -f2 -d':' | tr -d '\t'

(2). api서버의 url, port 확인

api 서버의 url은 아래의 명령어로 확인이 가능합니다. 

$ kubectl config view | grep server | cut -f 2- -d ":" | tr -d " "

(3). api 서버에 http request 보내서 인증 확인(클라이언트는 vscode의 rest client를 사용하였습니다.)

HTTP GET 요청을 https://<apiserver>/apis에 접근하면 403에러가 발생합니다.

anonymous 사용자로 인증은 되지만 인가를 해주지 않습니다.

# 토큰을 넣지 않으면 annoymous 사용자로 403에러가 발생
GET https://{{k8s_server}}/apis

HTTP/1.1 403 Forbidden
Cache-Control: no-cache, private
Content-Type: application/json
X-Content-Type-Options: nosniff
Date: Wed, 11 Aug 2021 05:35:21 GMT
Content-Length: 189
Connection: close

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "forbidden: User \"system:anonymous\" cannot get path \"/apis\"",
  "reason": "Forbidden",
  "details": {},
  "code": 403
}

 

(4) 401 인증 에러 확인

직접 401 인증에러를 확인하려면 http header에 인증되지 않은 토큰을 넣어 확인할 수 있습니다.

Authorization: Bearer test 를 헤더에 추가하여 https://<apiserver>/apis 에 request를 보냅니다.

# 직접 401에러를 확인하고싶다면 bearer토큰을 이상하게 발급해줘서 확인합니다.
GET https://{{k8s_server}}/apis
Authorization: Bearer mytoken

HTTP/1.1 401 Unauthorized
Cache-Control: no-cache, private
Content-Type: application/json
Date: Wed, 11 Aug 2021 05:36:22 GMT
Content-Length: 129
Connection: close

{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {},
  "status": "Failure",
  "message": "Unauthorized",
  "reason": "Unauthorized",
  "code": 401
}

 

(5) 200 ok

헤더에 인증된(1번에서 얻어온) bearer 토큰을 넣어 https://<apiserver>/apis 에 request를 보내면 쿠버네티스 서버의 api 목록을 확인할 수 있습니다.(response는 생략)

GET https://{{k8s_server}}/apis
Authorization: Bearer {{default_token}}

 

 

(6) 403 인가되지않은 사용자

클러스터의 pod 목록을 출력하기위해 아래와 같은 request를 보내면 default ServiceAccount에 대한 인가가 되지 않아 오류가 발생하는걸 확인할 수 있습니다.(response 생략)

https://<apiserver>/api/v1/pods

GET https://{{k8s_server}}/api/v1/namespaces
Authorization: Bearer {{my_token}}

 

 

2. 쿠버네티스 api 서버의 인증 인가 방법

  • Resource는 쿠버네티스 resource를 칭합니다.
  • Role은 resource에 할수 있는 행위를 말합니다.
  • RoleBinding은 롤과 사용자를 연결하며
  • Service Account, Users, User group은 사용자를 의미합니다.
  • role이나 rolebinding앞에 cluster가 붙는경우에는 namespace와 관계없이 resource에 접근할 수 있게됩니다.
  • 반대로 role이나 rolebinding만 사용하면 지정한 namespace에 있는 리소스에만 접근이 가능합니다.

 

직접 생성하는 예제입니다.

 

(1). ServiceAccount 생성

apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-service-account

 

(2). 클러스터 전체의 pod를 조회할수 있는 ClusterRole 생성

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: my-cluster-role
rules:
- apiGroups:
  - "" 
  resources:
  - pods
  verbs:
  - get
  - list

(3). ClusterRoleBinding을 통해 service account와 clusterRole 연결

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: my-cluster-role-binding
subjects:
- kind: ServiceAccount
  name: my-service-account
  namespace: default
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: my-cluster-role

(4). 생성한 ServiceAccount의 토큰을 헤더에 실어 api서버에 request

https://<apiserver>/api/pods
-> 200 ok
https://<apiserver>/api/services
-> 403 forbidden

# pod에 대한 권한만 줬으므로 services는 403

 

 

 

3. 내가 만든 pod이 쿠버네티스 서버에 접근하도록 하는 방법

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  serviceAccountName: my-service-account
  containers:
  - image: nginx
    name: mypod

또는

$ kubectl run mypod --image=nginx --restart=Never --serviceaccount=my-service-account

 

위 방법으로 pod에 serviceaccount를 연결해주면 pod은 serviceaccount에 binding된 role 만큼 쿠버네티스 api서버에 접근할 수 있습니다.

(컨테이너에 접근하면 /var/run/secrets/kubernetes.io/serviceaccount 인증서와 토큰이 생성되어 있습니다)

 

테스트용으로 pod의 이미지를 nginx로 설정했지만, 이미지가 api 서버 애플리케이션이라면 kubectl 명령어를 몰라도 쿠버네티스를 조작할 수 있는 클라이언트가 될 수도 있고, 쿠버네티스 operator를 띄우면 해당팟에게 쿠버네티스의 운영, 관리를 위임할 수 있습니다. 

 

 

반응형

댓글