클러스터 차원에서의 EKS 보안 기본개념

2021-11-07

.

Data_Engineering_TIL(20211107)

[학습자료]

“클라우드 네이티브를 위한 쿠버네티스 실전 프로젝트” 책을 읽고 정리한 내용입니다.

** 동양북스, 아이자와 고지&사토 가즈히코 지음, 박상욱 옮김

참고자료 URL : https://github.com/dybooksIT/k8s-aws-book

“Horizontal Pod Autoscaler를 이용한 EKS 파드 오토스케일링 실습”에 이어서 공부한 내용을 정리한 내용임

** URL : https://minman2115.github.io/DE_TIL303

[학습내용]

  • 인증

쿠버네티스 클러스터를 조작할때는 kubectl이라는 명령어를 사용한다. 이는 EKS에서도 동일하다. EKS에서는 IAM을 사용한 인증, 인가 기능을 제공하며 AWS CLI와 연결해서 인증하는 것도 가능하다. AWS CLI 명령어를 이용해서 설정하는 방법은 아래와 같다. AWS CLI 명령어로 aws eks update-kubeconfig 명령을 실행하면 kubectl을 자동으로 설정할 수 있다.

# kubeconfig 자동설정 --name 뒤에는 클러스터 이름을 입력해주면 된다.
[ec2-user@ip-10-10-1-195 ~]$ aws eks update-kubeconfig --name eks-work-cluster
Added new context arn:aws:eks:ap-northeast-2:xxxxxxxxxx:cluster/eks-work-cluster to /home/ec2-user/.kube/config

이렇게 설정하면 kubectl은 AWS CLI 인증탐색 구조를 이용해서 EKS 인증이 가능해진다. 아래에 kubeconfig 명세내역은 kubectl 명령어 실행시 참조되는 내용이다.

[ec2-user@ip-10-10-1-195 ~]$ cat /home/ec2-user/.kube/config
apiVersion: v1
# kubeconfig를 실행할때 사용할 인증서와 접속정보가 자동으로 설정됨
clusters:
- cluster:
    certificate-authority-data: xxxxxxxxxxxxx
    server: https://yyyyyyyyyyy.sk1.ap-northeast-2.eks.amazonaws.com
  name: eks-work-cluster.ap-northeast-2.eksctl.io
- cluster:
    certificate-authority-data: xxxxxxxxxxx
    server: https://yyyyyyyyyyy.sk1.ap-northeast-2.eks.amazonaws.com
  name: arn:aws:eks:ap-northeast-2:xxxxxxxxxxx:cluster/eks-work-cluster
contexts:
- context:
    cluster: eks-work-cluster.ap-northeast-2.eksctl.io
    namespace: eks-work
    user: minsu.park@eks-work-cluster.ap-northeast-2.eksctl.io
  name: eks-work
- context:
    cluster: eks-work-cluster.ap-northeast-2.eksctl.io
    user: minsu.park@eks-work-cluster.ap-northeast-2.eksctl.io
  name: minsu.park@eks-work-cluster.ap-northeast-2.eksctl.io
- context:
    cluster: arn:aws:eks:ap-northeast-2:xxxxxxxxxxx:cluster/eks-work-cluster
    user: arn:aws:eks:ap-northeast-2:xxxxxxxxxxx:cluster/eks-work-cluster
  name: arn:aws:eks:ap-northeast-2:xxxxxxxxxxx:cluster/eks-work-cluster
current-context: arn:aws:eks:ap-northeast-2:xxxxxxxxxxx:cluster/eks-work-cluster
kind: Config
preferences: {}
# kubeconfig를 실행할때 aws 명령에 있는 eks get-token 등의 설정이 자동으로 추가됨
users:
- name: minsu.park@eks-work-cluster.ap-northeast-2.eksctl.io
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - eks
      - get-token
      - --cluster-name
      - eks-work-cluster
      - --region
      - ap-northeast-2
      command: aws
      env:
      - name: AWS_STS_REGIONAL_ENDPOINTS
        value: regional
      interactiveMode: IfAvailable
      provideClusterInfo: false
- name: arn:aws:eks:ap-northeast-2:xxxxxxxxxxx:cluster/eks-work-cluster
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - --region
      - ap-northeast-2
      - eks
      - get-token
      - --cluster-name
      - eks-work-cluster
      command: aws

kubeconfig는 아래와 같은 특징이 있다.

.clusters[].cluster에서는 어떤 클러스터에 인증할지 설정

.users[].user에서는 어떤 사용자로 인증할지 설정

.contexts[].context에서는 클러스터와 사용자를 연결

우리가 실습한 예제는 eks-work-cluster라는 클러스터에 대해서 aws --region ap-northeast-2 eks get-token --cluster-name eks-work-cluster라는 명령으로 확인한 토큰을 통해 인증한다. 기본값으로 사용하는 네임스페이스는 eks-work이다.

  • 인가

kubectl로 접속한 요청이 정상적으로 인증된 후에는 요청한 명령이 허가된 명령인지 아닌지를 체크하고 명령을 날릴 필요가 있다. 쿠버네티스에서는 Role-Based Access Control(RBAC)라는 기능을 이용해서 구현한다. 구체적으로는 Role과 RoleBinding이라는 쿠버네티스 오브젝트를 사용해서 설정한다. 롤 오브젝트에는 어떤 명령을 사용할 수 있도록 허가할 것인가에 대한 권한셋과 같은 것을 정의하고, 롤바인딩 오브젝트에는 어떤 사용자에게 어떤 롤을 부여할 것인지 정의한다. EKS의 경우에는 aws-auth라는 이름의 컨피그맵 안에 AWS CLI 인증정보로 설정한 IAM 사용자, IAM 역할의 AWS 리소스 이름, 쿠버네티스 오브젝트로 그룹을 연결해놓고 롤바인딩으로 그 그룹과 롤을 연결시키는 구조이다.

RBAC 구조

1

예를 들어서 시스템 관리자에게는 클러스터의 모든 조작 권한을 부여하지만 어플리케이션 개발자에게는 특정 리소스에만 접속 가능하도록 권한을 부여할 수 있다. 지금까지 했던 모든실습에서는 kubectl을 사용했던 사용자에게 클러스터의 모든 권한이 부여되었지만, 이번에는 어플리케이션 개발자로 리소스 접속이 제한된 사용자를 예를 들어서 진행해보자. 특정 네임스페이스(예시로 rbac-test-ns)의 파드와 파드 로그, 디플로이먼트와 리플리카셋, 서비스만 참조 가능한 사용자를 등록해보자.

[RBAC 실습]

먼저 아래 명령어와 같이 롤과 롤바인딩을 등록한다.

[ec2-user@ip-10-10-1-195 security]$ pwd
/home/ec2-user/k8s-aws-book/security

[ec2-user@ip-10-10-1-195 security]$ ll
total 236
-rw-rw-r-- 1 ec2-user ec2-user 222723 Oct 18 13:49 calico.yml
-rw-rw-r-- 1 ec2-user ec2-user    160 Oct 18 13:49 network-policy-all-deny.yaml
-rw-rw-r-- 1 ec2-user ec2-user    429 Oct 18 13:49 network-policy-allow-http-from-serviceB2ServiceA.yaml
-rw-rw-r-- 1 ec2-user ec2-user    580 Oct 18 13:49 network-policy-sample-serviceA.yaml
-rw-rw-r-- 1 ec2-user ec2-user    752 Oct 18 13:49 rbac.yaml
    
# 지정한 그룹에 rbac-test-nc의 특정 리소스에만 참조를 허가하는 예시
[ec2-user@ip-10-10-1-195 security]$ vim rbac.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: rbac-test-ns
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rbac-test-role
rules:
# 허가할 조작 설정
- apiGroups: ["extensions", "apps", ""]
  resources: ["pods","pods/log","deployments","replicasets","services"]
  verbs: ["get", "watch", "list"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: rbac-test-role-binding
  # 대상 네임스페이스에만 조작 허가
  namespace: rbac-test-ns
roleRef:
  kind: ClusterRole
  name: rbac-test-role  # 클러스터롤 이름 설정
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: Group
  name: rbac-test-group  # 허가할 그룹 설정
  apiGroup: rbac.authorization.k8s.io
    
[ec2-user@ip-10-10-1-195 security]$ kubectl apply -f rbac.yaml
namespace/rbac-test-ns created
clusterrole.rbac.authorization.k8s.io/rbac-test-role created
rolebinding.rbac.authorization.k8s.io/rbac-test-role-binding created

그런 다음에 어플리케이션 개발자로 가정하는 IAM 계정을 아래와 같이 생성해준다.

2

그런 다음에 aws-auth에 롤바인딩의 .subjects[].name에서 설정한 그룹 이름(rbactest-group)과 IAM 사용자 또는 IAM 역할의 ARN 페어를 설정하면 EKS쪽 인증, 인가 설정의 매핑이 이루어진다. 또 여기서 지정하는 IAM 사용자는 클러스터를 생성할때 사용한 IAM 사용자와 다른 IAM 사용자이다. 사용자를 신규로 생성하고, 그 사용자의 ARN을 설정하자 (여기서는 minsu.park_test라는 사용자를 생성했다.)

[ec2-user@ip-10-10-1-195 security]$ eksctl create iamidentitymapping --region ap-northeast-2 --cluster eks-work-cluster --username minsu.park_test --group rbac-test-group --arn arn:aws:iam::xxxxxxxxxxxxxx:user/minsu.park_test
2021-11-07 07:49:34 [ℹ]  eksctl version 0.70.0
2021-11-07 07:49:34 [ℹ]  using region ap-northeast-2
2021-11-07 07:49:34 [ℹ]  adding identity "arn:aws:iam::xxxxxxxxxxxxxx:user/minsu.park_test" to auth ConfigMap

# minsu.park_test의 accesskey와 privatekey를 EKS 클라이언트 EC2에 아래와 같이 넣어준다.
[ec2-user@ip-10-10-1-195 security]$ aws configure
AWS Access Key ID [****************kkkk]: XXXXXXXXXXXXXXXXX
AWS Secret Access Key [****************tttt]: YYYYYYYYYYYYYYYYYYY
Default region name [ap-northeast-2]:
Default output format [json]:

# 기존에 사용하던 eks-work 네임스페이스로 변경
[ec2-user@ip-10-10-1-195 security]$ kubectl config use-context eks-work
Switched to context "eks-work".

# 기본 네임스페이스의 파드, 디플로이먼트, 서비스를 참조할 수 없는 것을 확인할 수 있다. (다른 리소스도 마찬가지임)
[ec2-user@ip-10-10-1-195 security]$ kubectl get pod,deployments,replicaset,service
Error from server (Forbidden): pods is forbidden: User "minsu.park_test" cannot list resource "pods" in API group "" in the namespace "eks-work"
Error from server (Forbidden): deployments.apps is forbidden: User "minsu.park_test" cannot list resource "deployments" in API group "apps" in the namespace "eks-work"
Error from server (Forbidden): replicasets.apps is forbidden: User "minsu.park_test" cannot list resource "replicasets" in API group "apps" in the namespace "eks-work"
Error from server (Forbidden): services is forbidden: User "minsu.park_test" cannot list resource "services" in API group "" in the namespace "eks-work"
        
# rbac-test-ns 네임스페이스의 파드, 디플로이먼트, 서비스는 참조가능
[ec2-user@ip-10-10-1-195 security]$ kubectl get pod,deployments,replicaset,service -n rbac-test-ns
No resources found in rbac-test-ns namespace.

# 네임스페이스 'default'에 리소스 추가는 허가되지 않음
[ec2-user@ip-10-10-1-195 security]$ kubectl create deployment tnginx-test --image=nginx:latest
error: failed to create deployment: deployments.apps is forbidden: User "minsu.park_test" cannot create resource "deployments" in API group "apps" in the namespace "eks-work"

# 네임스페이스 'rbac-test-ns'에 리소스 추가도 허가되지 않음
[ec2-user@ip-10-10-1-195 security]$ kubectl create deployment tnginx-test --image=nginx:latest -n rbac-test-ns
error: failed to create deployment: deployments.apps is forbidden: User "minsu.park_test" cannot create resource "deployments" in API group "apps" in the namespace "rbac-test-ns"

실습 종료후 계정원복

아래와 같이 테스트 용도로 생성한 IAM 계정인 minsu.park_test를 삭제해준다.

3

그리고 eks client에서도 기존에 사용하던 accesskey, private key로 원복시켜준다.

[ec2-user@ip-10-10-1-195 security]$ aws configure
AWS Access Key ID [****************TI2N]: KKKKKKKKKKKKKKKK
AWS Secret Access Key [****************rDle]: MMMMMMMMMMMMMMMMMM
Default region name [ap-northeast-2]:
Default output format [json]:

# 아래와 같이 원래 admin 권한으로 돌아온 것을 확인할 수 있다.
[ec2-user@ip-10-10-1-195 security]$ kubectl get pod,deployments,replicaset,service
NAME                              READY   STATUS      RESTARTS   AGE
pod/backend-app-7fb899969-bs798   1/1     Running     0          170m
pod/backend-app-7fb899969-f752z   1/1     Running     0          9d
pod/batch-app-1636272000-pww72    0/1     Completed   0          6m34s
pod/batch-app-1636272300-9mtrz    0/1     Completed   0          93s

NAME                          READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/backend-app   2/2     2            2           19d

NAME                                    DESIRED   CURRENT   READY   AGE
replicaset.apps/backend-app-7fb899969   2         2         2       19d

NAME                          TYPE           CLUSTER-IP     EXTERNAL-IP                                                                    PORT(S)          AGE
service/backend-app-service   LoadBalancer   10.100.92.76   xxxxxxx-yyyyyyy.ap-northeast-2.elb.amazonaws.com   8080:30609/TCP   19d