Kubernetes : API Server 보안 (Securing API Server)

Jiyoon·2022년 2월 7일
0

Kubernetes

목록 보기
10/10
post-thumbnail

K8S 인증에 대한 이해

API server에 요청을 하는 client를 authenticate, authorizate하는 기능을 하는 플러그인을 이용해 인증단계를 거칠 수 있다.
API server가 요청을 받으면, ㅇ니증 플러그인 목록의 각각에게 요청을 전달해서 신원을 확인한다.
Username, ID, Group 정보를 return 받은 후 승인 단계로 넘어간다. Client의 정보를 API server가 저장하지는 않음

등장인물 (Users and Groups)

User

Request를 받는 K8S API server 입장에서 client는 크게 2가지로 구분된다.

  • Actual Humans
  • Pods

Pods는 ServiceAccount라는 방식을 이용해서 API server에 접근하며, 이는 cluster 내에 service account resource를 생성하고 저장해서 pod는 이를 통해 API server로 통신하는 방식이다.

Group

User나 Service Account는 하나 이상의 group에 속할 수 있고, group마다 권한을 부여할 수 있다.

Note) Built-in groups
System built group은 조금 특별한 의미를 가지고 있는데

  • system:unauthenticated : 여러개의 플러그인들 중 어떤 것도 이 request의 client를 식별할 수 없을 때 system:unauthenticated group으로 포함됨
  • system:authenticated : 성공적으로 client가 식별되었을 때 이 그룹으로 편성됨
  • system:serviceaccounts : system의 모든 service account 포함
  • system:serviceaccounts:<namespace> : specific namespace에 포함되는 service account가 이 그룹으로 편성됨

Service Account

Service account는 pod가 API server와 통신할 때 식별자 역할을 한다.
Token file은 service account의 인증 토큰을 갖고 있으며, pod 토큰을 이용한 인증과정은 아래! 👇
1. Pod가 토큰을 가지고 API server에 연결 요청
2. API server의 인증 플러그인이 service account를 인증
3. Service account의 사용자 이름을 API server core로 다시 전달
(Service acoount의 사용자 이름은 `System: serviceaccount::과 같이 구성된다)
4. API server는 이 사용자 이름을 승인 플러그인으로 전달하고, 해당 pod의 application이 수행하려고 하는 동작이 service-account에 의해 허가되는지 여부를 결정한다.

Service Account 특징

  • Service account도 pod, configmap과 같은 Resource로 취급됨
  • 범위는 namespace 별로 지정됨. Namespace를 넘어서 할당이 불가능하다
  • namespace에는 여러 개의 service account가 존재할 수 있다
  • pod는 service account만 연결 가능하고, 여러 pod가 하나의 service account를 사용 가능하다.

Service Account 생성해보기


$ kubectl create serviceaccount foo -n chapter12
serviceaccount "foo" created

$ kubectl get sa -n chapter12
NAME      SECRETS   AGE
default   1         26s
foo       1         8s

$ kubectl describe sa foo -n chapter12
Name:
Namespace:
Labels:
Annotations:
Image pull secrets:  <none>
Mountable secrets: foo-token-72z4h
Tokens: foo-token-72z4h
events: <none>

Service account를 생성하면, custom token secret이 만드ㄹ어지고, 이게 service account와 연결되는 부분을 볼 수 있다.(foo-token-72z4h) 참고로 service account에서 사용되는 인증 토큰은 JWT (JSON Web Token) 방식.

Pod에 Service Account 할당하고, API server와 통신해보기

생성한 foo라는 service account를 사용해 pod를 배포해보면

apiVersion: v1
kind: Pod
metadata:
    name: curl-custom-sa
    namespace: chapter12
spec:
    serviceAccountName: foo.  ### 여기
    containers:
    - name: main
      image: tutum/curl
      command: ['sleep', '999999']
    - name: ambassador
      image: luksa/kubectl-proxy:1.6.2

이 service account를 가지고 API server로 통신해보면


$ kubectl exec -it curl-custom-sa -c main curl localhost:8001/api/v1
/pods -n chapter12
{
  "kind": "Status",
  "apiVersion": "v1",
  "metadata": {
  },
  "status": "Failure",
  "message": "pods is forbidden: User \"system:serviceaccount:chapter12:
foo\" cannot list resource \"pods\" in API group \"\" at the cluster
scope",
  "reason": "Forbidden",
  "details": {
    "kind": "pods"
  },
"code": 403 }

403 권한 에러로 통신이 불가능하다😿
그럼 이 service account에 권한을 부여해주려면 어떻게 해야할까? ➡️ RBAC plugin을 이용함.

RBAC 플러그인이란

K8S는 RBAC 승인 플러그인을 통해 권한을 제어하고, 이 RBAC resource를 통해서 클러스터에 대한 접근을 관리하면서 API Server securing을 한다고 볼 수 있다.

API server는 REST interface를 노출하므로, 사용자는 HTTP 요청을 통해 server로 작업을 요청하는데, 이 때 사용자는 자격증명 (인증 토큰, 사용자 이름, 암호.. 등등) 을 통해 인증한다.
이 때 Authorization plugin을 통해 사용자의 요청이 수행 가능한지 여부를 확인한다.

Kubernetes에서 할 수 있는 actions에 대한 이해

Kubernetes에서 취할 수 있는 actions에는

  • GET (ex. Pod 조회)
  • POST (ex. Pod 생성)
  • PUT (ex. Secret 업데이트)
    가 있고, 이는 HTTP Method와 연결된다! 이 action 들을 RBAC rule에 명시하게 된다.

이 RBAC Rule은 pod, service, secret과 같은 resource 유형에도 적용할 수 있고, resource의 특정 instance에도 적용 가능하다.

RBAC Resources (RBAC 플러그인에 필요한 4가지 등장인물)

RBAC Authorization Rule은 4가지 resource로 구성되며, 크게 2가지로 그룹화된다.
-Roles / ClusterRoles : 특정 resource에 대한 허가 여부를 지정

  • RoleBinding / ClusterRoleBinding: Role에 정의된 내용을 User 나 User group에 지정 (bond해줌!)

Role / Role Binding

  • Role과 Role Binding은 모두 namespace 한정으로 생성한다. Namespace를 넘어갈 수가 없다
    (==같은 namespace의 resource들에만 적용 가능)
‼️미션
- namespace `cloudswu` 에서 pod를 get / list 할 수 있도록 허용하는 service-reader라는 role을 만들어보자!

————-

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: cloudswu
  name: service-reader
rules:
- apiGroups: [""]
  verbs: ["get", "list"]
  resources: ["pods"]
$ kubectl create -f service-reader.yaml -n cloudswu

YAML파일 생성이 귀찮다면 CLI로도 가능하다

$ kubectl create role <role_name> —verb=get —verb=list —resource=pod -n cloudswu

Role을 serviceAccount에 binding한다

$ kubectl create rolebinding <rb_name> —role=<role_name> —serviceaccount=<sa_name> -n foo

Cluster Role / Cluster Role Binding

  • Cluster 레벨의 resource에 설정 가능한 RBAC ㄹㅣ소스
‼️미션
- persistvolume을 get / list 할 수 있도록 허용하는 pv-reader 라는 role을 만들어보자!

———

$ kubectl create clusterrole pv-reader --verb=get,list --
resource=persistentvolumes
clusterrole.rbac.authorization.k8s.io "pv-reader" created

여기에 clusterRoleBinding을 생성한다

$ kubectl create clusterrolebinding <pv-test-rolebinding> --clusterrole=pv-reader --
serviceaccount=<sa_name>:default

clusterrolebinding.rbac.authorization.k8s.io "pv-test" created

이 serviceAccount가 binding된 pod에 직접 접속해서 persistent volume을 조회하면 조회가능하다.

ClusterRole은 항상 clusterRoleBinding과 연결되어야하나요?

Cluster-role도 namespace마다 분리되는 role-binding이 가능하다.

사용 case별 ClusterRole / Role / ClusterRoleBinding / RoleBinding 조합

  • 특정 namespace에서만 namespace 내의 resource를 사용하도록 한정해야하는 경우 ➡️ Role + RoleBinding 사용
  • 특정 namespace에서 사용하지만 1개이상 multi namespace에서 동일한 role로 설정이 중복되는 경우 ➡️ ClusterRole + namespace 별 RoleBinding 사용
  • namespace에 한정되지 않는 경우 ➡️ ClusterRole + ClusterRoleBinding

Default Roles and bindings

Kubernetes API server가 시작될 때 제공되는 기본 ClusterRole과 ClusterRoleBinding이 있으며 이 중 view, edit, admin, cluster-admin이 중요하다

  • View: Role / RoleBinding / Secret 을 제외한 namespace 내의 모든 resource를 읽을 수 있음
  • Edit : namespace의 resource를 수정할 수 있음 / Secret도 읽고 수정 가능 / Role, RoleBinding을 보거나 수정은 허용되지 않음
  • Admin : namespace의 resource를 제어 가능 ResourceQuota와 namespace자체를 제외한 리소스를 읽고 수정 가능. 그럼 Edit와 차이는? Role / RoleBinding을 읽고 수정 가능
  • Cluster-admin : Kubernetes cluster를 제어 가능

그밖의 Default Cluster Role은 system: 접두사 로 시작하는 룰이 있는데 이는 각 특성에 맞춰서 다양한 K8S 구성 요소를 제어하기 위해 사용된다.

권한을 현명하게 부여하기

  • 모든 사용자에게 cluster-admin rule을 부여하는것은 좋지 못하다.
    1) 각 pod에 특정한 serviceAccount를 생성해 binding하고, roleBinding을 통해 맞춤형 role과 연관시키는게 좋음

Quiz

Ex. Namespace “cloud” 안에 읽기권한만 필요한 Pod A가 있고, 수정 권한이 필요한 다른 pod B가 있다.
이럴 때 serviceAccount를 어떻게 지정해야할까?

profile
Jiyoon in cloud valley, Change the world Why Not? / 오픈소스 생태계를 잘 이해하는 Cloud engineer가 되고 싶은 지윤

0개의 댓글