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

2021-11-20

.

Data_Engineering_TIL(20211120)

[학습자료]

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

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

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

“클러스터 차원에서의 EKS 보안 기본개념”에 이어서 공부한 내용을 정리한 내용임

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

[학습내용]

  • 파드에 부여하는 호스트 권한 제어

EKS 클러스터에서는 데이터 플레인 노드 위에서 다양한 파드가 동작하게 된다. 하지만 클러스터를 운영하면서 아무나 어떤 파드든 무조건 생성해서는 안된다. 쿠버네티스에서는 이러한 고민을 해결하기 위해서 파드에 부여할 권한을 관리하는 Pod Security Policy(이하 PSP)라는 기능을 제공한다. PSP에서 설정할 수 있는 항목은 여러가지 이지만, 여기서는 특정 권한을 갖는 특정 컨테이너를 예시로 한다. 현재 클러스터에서는 디폴트로 PSP가 활성화 되어 있지만 아무 제한사항이 설정되어 있지 않은 상태이다. 다시말해서 어떤 조작이던지 가능한 상태이다. 예를 들어서 파드를 privileged(특권) 컨테이너로 동작시켜 노드 쪽 권한을 사용하도록 할 수 있다.

# 디폴트 PSP에는 아래와 같이 아무 제한사항이 없다.
[ec2-user@ip-10-10-1-125 eks-env]$ kubectl get psp
NAME             PRIV   CAPS   SELINUX    RUNASUSER   FSGROUP    SUPGROUP   READONLYROOTFS   VOLUMES
eks.privileged   true   *      RunAsAny   RunAsAny    RunAsAny   RunAsAny   false            *

# PSP 값을 바꿔보자.
[ec2-user@ip-10-10-1-125 eks-env]$ kubectl edit psp eks.privileged
# 아래의 config 값에서 privileged: true를 privileged: false로 바꿔준다.

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"policy/v1beta1","kind":"PodSecurityPolicy","metadata":{"annotations":{"kubernetes.io/description":"privileged allows full unrestricted access to pod features, as if the PodSecurityPolicy controller was not enabled.","seccomp.security.alpha.kubernetes.io/allowedProfileNames":"*"},"labels":{"eks.amazonaws.com/component":"pod-security-policy","kubernetes.io/cluster-service":"true"},"name":"eks.privileged"},"spec":{"allowPrivilegeEscalation":true,"allowedCapabilities":["*"],"fsGroup":{"rule":"RunAsAny"},"hostIPC":true,"hostNetwork":true,"hostPID":true,"hostPorts":[{"max":65535,"min":0}],"privileged":true,"readOnlyRootFilesystem":false,"runAsUser":{"rule":"RunAsAny"},"seLinux":{"rule":"RunAsAny"},"supplementalGroups":{"rule":"RunAsAny"},"volumes":["*"]}}
    kubernetes.io/description: privileged allows full unrestricted access to pod features,
      as if the PodSecurityPolicy controller was not enabled.
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
  creationTimestamp: "2021-11-20T04:08:27Z"
  labels:
    eks.amazonaws.com/component: pod-security-policy
    kubernetes.io/cluster-service: "true"
  name: eks.privileged
  resourceVersion: "200"
  selfLink: /apis/policy/v1beta1/podsecuritypolicies/eks.privileged
  uid: 693f031c-5643-4132-9e84-2deaf20128f0
spec:
  allowPrivilegeEscalation: true
  allowedCapabilities:
  - '*'
  fsGroup:
    rule: RunAsAny
  hostIPC: true
  hostNetwork: true
  hostPID: true
  hostPorts:
  - max: 65535
    min: 0
  privileged: true  <-- 이 부분을 false로 바꿔준다.
  runAsUser:
    rule: RunAsAny
  seLinux:

# 수정후 wq! 로 나오면 아래와 같이 config가 변경되었다는 메세지가 뜬다.
podsecuritypolicy.policy/eks.privileged edited

# 수정후 nginx 파드를 새로 띄우면 정상동작한다.
[ec2-user@ip-10-10-1-125 eks-env]$ kubectl apply -f - <<EOF
> apiVersion: v1
> kind: Pod
> metadata:
>     name: nginx
> spec:
>     containers:
>         - name: nginx
>           image: nginx:latest
> EOF
pod/nginx created

[ec2-user@ip-10-10-1-125 eks-env]$ kubectl get pod nginx
NAME    READY   STATUS    RESTARTS   AGE
nginx   1/1     Running   0          83s

[ec2-user@ip-10-10-1-125 eks-env]$ kubectl delete pod nginx
pod "nginx" deleted

# 그러나 아래와 같이 privileged container로 실행하려고 하면 에러가 발생한다.
[ec2-user@ip-10-10-1-125 eks-env]$ kubectl apply -f - <<EOF
> apiVersion: v1
> kind: Pod
> metadata:
>     name: nginx
> spec:
>     containers:
>         - name: nginx
>           image: nginx:latest
>           securityContext:
>               privileged: true
> EOF

Error from server (Forbidden): error when creating "STDIN": pods "nginx" is forbidden: PodSecurityPolicy: unable to admit pod: [spec.containers[0].securityContext.privileged: Invalid value: true: Privileged containers are not allowed]

# 변경한 PSP 원복
[ec2-user@ip-10-10-1-125 eks-env]$ kubectl edit psp eks.privileged
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"policy/v1beta1","kind":"PodSecurityPolicy","metadata":{"annotations":{"kubernetes.io/description":"privileged allows full unrestricted access to pod features, as if the PodSecurityPolicy controller was not enabled.","seccomp.security.alpha.kubernetes.io/allowedProfileNames":"*"},"labels":{"eks.amazonaws.com/component":"pod-security-policy","kubernetes.io/cluster-service":"true"},"name":"eks.privileged"},"spec":{"allowPrivilegeEscalation":true,"allowedCapabilities":["*"],"fsGroup":{"rule":"RunAsAny"},"hostIPC":true,"hostNetwork":true,"hostPID":true,"hostPorts":[{"max":65535,"min":0}],"privileged":true,"readOnlyRootFilesystem":false,"runAsUser":{"rule":"RunAsAny"},"seLinux":{"rule":"RunAsAny"},"supplementalGroups":{"rule":"RunAsAny"},"volumes":["*"]}}
    kubernetes.io/description: privileged allows full unrestricted access to pod features,
      as if the PodSecurityPolicy controller was not enabled.
    seccomp.security.alpha.kubernetes.io/allowedProfileNames: '*'
  creationTimestamp: "2021-11-20T04:08:27Z"
  labels:
    eks.amazonaws.com/component: pod-security-policy
    kubernetes.io/cluster-service: "true"
  name: eks.privileged
  resourceVersion: "24940"
  selfLink: /apis/policy/v1beta1/podsecuritypolicies/eks.privileged
  uid: 693f031c-5643-4132-9e84-2deaf20128f0
spec:
  allowPrivilegeEscalation: true
  allowedCapabilities:
  - '*'
  fsGroup:
    rule: RunAsAny
  hostIPC: true
  hostNetwork: true
  hostPID: true
  hostPorts:
  - max: 65535
    min: 0
  runAsUser:
    rule: RunAsAny
  seLinux:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  volumes:
  - '*'
  privileged: true           # 이 행을 추가해준다.

# 변경후 아래와 같이 config가 변경되었다고 뜬다.
podsecuritypolicy.policy/eks.privileged edited

PSP를 사용해서 파드에서 사용할 수 있는 권한을 제어함으로써 노드를 보호하는 구조를 알아보았다. 위에 예시는 기본 파드 PSP를 사용해서 모든 사용자에 대해 Privileged 컨테이너 동작을 금지시켰지만 특정 사용자에게만 권한 제어를 적용하고 싶을 경우도 있을것이다. 그 경우에는 아래 그림과 같이 별도로 PSP를 생성해서 그 PSP를 사용하는 것을 롤로 선언하고 롤바인딩으로 롤과 사용자를 매핑시키면 PSP를 적용할 수 있다.

1