LabHub
배우기 러닝패스 코스

CKS — Kubernetesセキュリティスペシャリスト

デフォルト拒否から始めるクラスタ構築

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

네임스페이스 하나를 기본 거부 상태로 만든 뒤 필요한 통로만 하나씩 다시 여는 순서를 손에 익히고, 컨트롤 플레인 설정 파일에서 무엇을 확인해야 하는지 직접 써 봅니다.

왜 중요한가

쿠버네티스의 기본값은 전부 열려 있습니다. 정책이 하나도 없는 파드는 클러스터의 어떤 파드와도 통신할 수 있고, 노드의 메타데이터 주소에도 그대로 도달합니다. 그래서 보안 설계의 첫 동작은 무언가를 막는 규칙을 추가하는 것이 아니라, 전부 막아 놓고 필요한 것만 되돌리는 것입니다. 이 순서를 뒤집으면 "무엇을 빠뜨렸는지" 를 영원히 알 수 없습니다. 설정 파일 감사도 같은 발상입니다. 실행 중인 프로세스를 관찰하는 것보다 매니페스트 한 장을 읽는 쪽이 빠르고, 무엇이 빠져 있는지를 목록으로 만들 수 있습니다.

이 실습 환경에는 실제 데이터플레인이 없으므로 정책이 트래픽을 정말 끊는지는 확인할 수 없습니다. 채점은 오브젝트의 스펙이 의도대로 쓰였는지를 봅니다. 시험에서도 요구하는 것은 정확한 스펙입니다.

단계

  1. 네임스페이스 cks-net 을 만들고 라벨 tier=restricted 를 붙인다.
  2. cks-net 에 NetworkPolicy default-deny-all 을 만든다. podSelector 는 비우고 policyTypesIngressEgress 를 모두 적되, ingress/egress 규칙은 하나도 두지 않는다.
  3. cks-net 에 NetworkPolicy allow-dns-egress 를 만든다. 모든 파드를 대상으로 하고 policyTypesEgress 만, egress 대상은 kubernetes.io/metadata.name=kube-system 라벨의 네임스페이스 안 k8s-app=kube-dns 라벨 파드이며 포트는 UDP 53 과 TCP 53 두 개다.
  4. cks-net 에 NetworkPolicy allow-frontend-to-api 를 만든다. 대상은 app=api 파드, ingress 허용 출처는 같은 네임스페이스의 app=frontend 파드, 포트는 TCP 8080 이다.
  5. cks-net 에 NetworkPolicy deny-node-metadata 를 만든다. 모든 파드 대상, policyTypesEgress, egress 대상은 ipBlock 으로 cidr: 0.0.0.0/0except: [169.254.169.254/32] 다.
  6. cks-netkubernetes.io/tls 타입 Secret shop-tls 를 만든다. tls.crttls.key 가 모두 비어 있지 않아야 한다.
  7. cks-net 에 Ingress shop 을 만든다. spec.tls[0]hostsshop.cks.local, secretNameshop-tls 이고, spec.rules[0].hostshop.cks.local 이며 경로 / 는 서비스 api 의 8080 포트로 보낸다.
  8. /root/cks-cluster-setup/kube-apiserver.yaml 에 CIS 권고를 반영한 정적 파드 매니페스트를 쓴다. kind: Pod, 컨테이너 이름은 kube-apiserver, command 배열에 --anonymous-auth=false, --authorization-mode=Node,RBAC, --profiling=false, --audit-log-path=/var/log/kubernetes/audit.log, --enable-admission-plugins=NodeRestriction,PodSecurity 가 들어가고 --insecure-port 로 시작하는 플래그는 하나도 없어야 한다.

참고

격리할 네임스페이스 만들기

네임스페이스 cks-net 을 만들고 라벨 tier=restricted 를 붙인다.

네임스페이스를 만들고 라벨을 붙입니다. kubectl create ns 뒤에 kubectl label ns 를 이어 쓰거나, 매니페스트 한 장으로 만들어도 됩니다.

ingress·egress 전부 막는 기본 정책

cks-net 에 NetworkPolicy default-deny-all 을 만든다. podSelector 는 비우고 policyTypesIngressEgress 를 모두 적되, ingress/egress 규칙은 하나도 두지 않는다.

podSelector: {} 는 네임스페이스의 모든 파드를 고릅니다. policyTypes 에 방향을 적되 ingress/egress 규칙 목록은 아예 두지 않으면 그 방향은 전부 거부됩니다.

DNS 만 예외로 여는 egress

cks-net 에 NetworkPolicy allow-dns-egress 를 만든다. 모든 파드를 대상으로 하고 policyTypesEgress 만, egress 대상은 kubernetes.io/metadata.name=kube-system 라벨의 네임스페이스 안 k8s-app=kube-dns 라벨 파드이며 포트는 UDP 53 과 TCP 53 두 개다.

kube-dns 파드는 kube-system 네임스페이스에 있고 k8s-app=kube-dns 라벨을 답니다. 네임스페이스는 kubernetes.io/metadata.name 라벨로 고를 수 있습니다. 53 포트는 UDP 와 TCP 둘 다 필요합니다.

필요한 파드 쌍만 여는 ingress

cks-net 에 NetworkPolicy allow-frontend-to-api 를 만든다. 대상은 app=api 파드, ingress 허용 출처는 같은 네임스페이스의 app=frontend 파드, 포트는 TCP 8080 이다.

podSelector 로 받는 쪽을 고르고, ingress[].from[].podSelector 로 보내는 쪽을 고릅니다. 포트를 적지 않으면 모든 포트가 열립니다.

노드 메타데이터로 나가는 길 도려내기

cks-net 에 NetworkPolicy deny-node-metadata 를 만든다. 모든 파드 대상, policyTypesEgress, egress 대상은 ipBlock 으로 cidr: 0.0.0.0/0except: [169.254.169.254/32] 다.

ipBlockcidr 하나에 except 목록을 붙일 수 있고, except 의 대역은 반드시 cidr 안에 들어 있어야 합니다.

Ingress 용 TLS Secret

cks-netkubernetes.io/tls 타입 Secret shop-tls 를 만든다. tls.crttls.key 가 모두 비어 있지 않아야 한다.

kubernetes.io/tls 타입의 Secret 은 tls.crttls.key 두 키가 반드시 있어야 합니다. openssl 로 자체 서명 인증서를 만들거나, 매니페스트에 base64 값을 직접 넣어도 됩니다.

Ingress 에 TLS 연결하기

cks-net 에 Ingress shop 을 만든다. spec.tls[0]hostsshop.cks.local, secretNameshop-tls 이고, spec.rules[0].hostshop.cks.local 이며 경로 / 는 서비스 api 의 8080 포트로 보낸다.

Ingress 의 spec.tlshosts 목록과 secretName 을 짝지어 적습니다. spec.rules 의 호스트와 spec.tls[].hosts 가 어긋나면 인증서가 붙지 않습니다.

kube-apiserver 매니페스트 감사

/root/cks-cluster-setup/kube-apiserver.yaml 에 CIS 권고를 반영한 정적 파드 매니페스트를 쓴다. kind: Pod, 컨테이너 이름은 kube-apiserver, command 배열에 --anonymous-auth=false, --authorization-mode=Node,RBAC, --profiling=false, --audit-log-path=/var/log/kubernetes/audit.log, --enable-admission-plugins=NodeRestriction,PodSecurity 가 들어가고 --insecure-port 로 시작하는 플래그는 하나도 없어야 한다.

정적 파드 매니페스트는 kind: Pod 이고 플래그는 spec.containers[0].command 배열에 들어갑니다. CIS 는 익명 인증 차단, Node+RBAC 인가, 프로파일링 비활성화, NodeRestriction 어드미션을 권고하고, 인증 없는 평문 포트 플래그는 아예 없어야 합니다.