Skip to content

필사 모드: CKS (Certified Kubernetes Security Specialist) 실전 모의고사 완전 정복

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

1. CKS 시험 개요

CKS(Certified Kubernetes Security Specialist)는 CNCF와 Linux Foundation이 제공하는 고급 Kubernetes 보안 자격증입니다.

| 항목 | 내용 |

| --------- | --------------------------------- |

| 시험 시간 | 120분 |

| 문제 유형 | 15~20개 실기 문제 (퍼포먼스 기반) |

| 합격 기준 | 67% 이상 |

| 선행 조건 | 현재 유효한 CKA 자격증 |

| 시험 환경 | 원격 감독, 브라우저 기반 터미널 |

| 유효 기간 | 2년 |

도메인별 비율

| 도메인 | 비율 |

| ---------------------------------------- | ---- |

| Cluster Setup | 10% |

| Cluster Hardening | 15% |

| System Hardening | 15% |

| Minimizing Microservice Vulnerabilities | 20% |

| Supply Chain Security | 20% |

| Monitoring, Logging and Runtime Security | 20% |

2. Kubernetes 보안 핵심 개념 요약

2.1 RBAC (Role-Based Access Control)

RBAC는 Kubernetes API 접근을 제어하는 핵심 메커니즘입니다. Role/ClusterRole은 권한을 정의하고, RoleBinding/ClusterRoleBinding은 그 권한을 주체(user, group, serviceaccount)에 바인딩합니다.

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

namespace: default

name: pod-reader

rules:

- apiGroups: ['']

resources: ['pods']

verbs: ['get', 'watch', 'list']

2.2 Pod Security Standards (PSS)

| 프로파일 | 설명 |

| ---------- | ------------------------------------ |

| Privileged | 제한 없음, 모든 권한 허용 |

| Baseline | 최소한의 제한, 알려진 권한 상승 방지 |

| Restricted | 강력한 보안 정책, 모범 사례 준수 |

2.3 Network Policy

NetworkPolicy는 Pod 간 트래픽을 L3/L4 수준에서 제어합니다. 기본적으로 모든 트래픽이 허용되며, NetworkPolicy를 적용하면 명시된 트래픽만 허용됩니다.

2.4 Falco 런타임 보안

Falco는 커널 시스템 콜을 모니터링하여 런타임 위협을 탐지합니다. 규칙 기반으로 의심스러운 활동을 감지하고 알림을 보냅니다.

2.5 Supply Chain Security

- **Image Scanning**: Trivy, Snyk으로 CVE 취약점 탐지

- **Image Signing**: Cosign으로 이미지 서명 및 검증

- **SBOM**: 소프트웨어 구성 요소 목록 (Software Bill of Materials)

- **Admission Controllers**: ImagePolicyWebhook으로 이미지 정책 강제

3. 개념 이해 문제 (Q1~Q55)

Cluster Setup (Q1~Q10)

A) NIST SP 800-190

B) CIS Kubernetes Benchmark

C) PCI DSS

D) ISO 27001

**정답**: B

**설명**: kube-bench는 CIS(Center for Internet Security) Kubernetes Benchmark를 기반으로 클러스터 구성 요소의 보안 설정을 자동으로 점검합니다. 마스터 노드, 워커 노드, etcd, API 서버 등을 검사합니다.

A) `/etc/kubernetes/manifests/kube-apiserver.yaml`의 `--etcd-encryption-key` 플래그

B) `/etc/kubernetes/encryption-config.yaml`을 kube-apiserver의 `--encryption-provider-config`로 지정

C) etcd의 `--cipher-suites` 플래그

D) kubelet의 `--encrypt-data` 플래그

**정답**: B

**설명**: etcd at-rest 암호화는 EncryptionConfiguration 리소스를 yaml 파일로 작성하고, kube-apiserver의 `--encryption-provider-config` 플래그로 해당 파일을 지정하여 활성화합니다. Secrets, ConfigMaps 등 특정 리소스 유형에 대해 암호화 프로바이더(aescbc, aesgcm, secretbox 등)를 설정합니다.

A) ConfigMap

B) Secret (type: kubernetes.io/tls)

C) PersistentVolume

D) ServiceAccount token

**정답**: B

**설명**: TLS 인증서와 개인키는 `kubernetes.io/tls` 타입의 Secret에 저장합니다. `tls.crt` 필드에 인증서, `tls.key` 필드에 개인키를 base64 인코딩하여 저장하며, Ingress 리소스의 `spec.tls` 섹션에서 이 Secret을 참조합니다.

A) NetworkPolicy로 169.254.169.254 주소 차단

B) Pod의 `hostNetwork: true` 설정

C) ServiceAccount automount 비활성화

D) PSP에서 hostPID 금지

**정답**: A

**설명**: AWS IMDSv1은 인증 없이 169.254.169.254에 접근하여 IAM 자격증명을 탈취할 수 있습니다. NetworkPolicy로 해당 IP 주소로의 egress를 차단하거나, IMDSv2로 업그레이드하여 hop limit을 1로 설정하면 컨테이너에서의 직접 접근을 방지할 수 있습니다.

A) podSelector

B) namespaceSelector

C) ipBlock

D) serviceSelector

**정답**: B

**설명**: `namespaceSelector`를 사용하면 특정 namespace 레이블을 가진 namespace의 Pod에서 오는 트래픽만 허용할 수 있습니다. `podSelector`와 함께 사용하면 특정 namespace 내 특정 Pod만 허용하는 세밀한 정책을 만들 수 있습니다.

A) 클러스터를 즉시 재시작

B) 해당 권고사항의 remediation 섹션 확인

C) 새 클러스터 생성

D) etcd 백업 삭제

**정답**: B

**설명**: kube-bench 결과의 각 [FAIL] 항목에는 remediation(수정 방법) 섹션이 포함되어 있습니다. 이 섹션에는 구체적인 수정 명령어나 설정 변경 방법이 기술되어 있으므로, 이를 먼저 확인하고 신중하게 적용해야 합니다.

A) `--anonymous-auth=false`

B) `--disable-anonymous=true`

C) `--allow-anonymous=false`

D) `--auth-anonymous=disabled`

**정답**: A

**설명**: kube-apiserver의 `--anonymous-auth=false` 플래그로 익명 인증을 비활성화할 수 있습니다. 이를 설정하면 인증되지 않은 요청이 system:anonymous 사용자로 처리되지 않고 거부됩니다.

A) `--peer-cert-file`, `--peer-key-file`, `--peer-trusted-ca-file`

B) `--tls-cert-file`, `--tls-key-file`

C) `--client-cert-auth`, `--trusted-ca-file`

D) `--peer-auth=tls`

**정답**: A

**설명**: etcd 피어 통신 TLS는 `--peer-cert-file`(피어 인증서), `--peer-key-file`(피어 개인키), `--peer-trusted-ca-file`(피어 CA 인증서) 세 가지 플래그로 설정합니다. `--peer-client-cert-auth=true`도 함께 설정하면 피어 클라이언트 인증도 강제할 수 있습니다.

A) 이벤트 메타데이터만

B) 요청 메타데이터와 요청 본문

C) 메타데이터, 요청 본문, 응답 본문 모두

D) 응답 본문만

**정답**: C

**설명**: 감사 로그 레벨은 None, Metadata, Request, RequestResponse 4단계입니다. RequestResponse는 가장 상세한 레벨로 이벤트 메타데이터, 요청 본문(request body), 응답 본문(response body)을 모두 기록합니다. 다만 데이터 양이 많아 스토리지 비용이 높습니다.

A) AlwaysAllow

B) NodeRestriction, PodSecurityAdmission 포함

C) AlwaysDeny

D) LimitRanger만 활성화

**정답**: B

**설명**: CIS Benchmark는 NodeRestriction(노드가 자신의 리소스만 수정 가능), PodSecurityAdmission(PSS 정책 적용), ResourceQuota, LimitRanger 등 보안 강화 admission controller를 활성화할 것을 권장합니다.

Cluster Hardening (Q11~Q22)

A) ServiceAccount에 `automountServiceAccountToken: false` 설정

B) Pod spec에 `serviceAccountName: none` 설정

C) RBAC에서 serviceaccount 리소스를 삭제

D) Secret 삭제

**정답**: A

**설명**: ServiceAccount 리소스에 `automountServiceAccountToken: false`를 설정하거나, Pod spec에 `automountServiceAccountToken: false`를 설정하면 ServiceAccount 토큰이 자동으로 마운트되지 않습니다. Pod 레벨 설정이 ServiceAccount 레벨 설정을 오버라이드합니다.

A) cluster-admin ClusterRole을 모든 ServiceAccount에 바인딩

B) 필요한 리소스와 동사(verbs)만 포함하는 맞춤형 Role 생성

C) RBAC를 비활성화하고 ABAC 사용

D) 모든 리소스에 wildcard(\*) 사용

**정답**: B

**설명**: 최소 권한 원칙은 필요한 작업에 최소한의 권한만 부여하는 것입니다. 특정 namespace의 특정 리소스에 대한 특정 동사만 허용하는 맞춤형 Role을 만들고, 필요한 주체에만 RoleBinding을 통해 부여해야 합니다.

A) `--authentication-token-webhook=true`, `--authorization-mode=Webhook`

B) `--anonymous-auth=true`

C) `--read-only-port=10255`

D) `--allow-all-requests=true`

**정답**: A

**설명**: kubelet 보안 강화를 위해 `--anonymous-auth=false`로 익명 접근을 차단하고, `--authentication-token-webhook=true`로 토큰 웹훅 인증을 활성화하며, `--authorization-mode=Webhook`으로 API 서버를 통한 권한 부여를 설정합니다.

A) 새 기능 추가를 위해

B) CVE 취약점 패치 및 보안 픽스 적용

C) 성능 향상을 위해

D) kubectl 버전 호환성

**정답**: B

**설명**: Kubernetes는 마이너 버전을 약 4개월 주기로 릴리스하며, 각 버전은 약 14개월간 지원됩니다. 업그레이드하지 않으면 CVE(Common Vulnerabilities and Exposures) 취약점이 패치되지 않아 보안 위험이 증가합니다. CKS 시험에서는 최신 지원 버전 유지를 권장합니다.

subjects:

- kind: Group

name: system:authenticated

roleRef:

kind: ClusterRole

name: cluster-admin

A) subjects 필드가 잘못됨

B) 인증된 모든 사용자에게 cluster-admin 권한 부여

C) ClusterRoleBinding 이름이 없음

D) apiGroup이 누락됨

**정답**: B

**설명**: `system:authenticated` 그룹은 인증된 모든 사용자를 포함합니다. 이 그룹에 cluster-admin을 바인딩하면 클러스터에 접근 가능한 모든 사용자가 최고 권한을 갖게 됩니다. 마찬가지로 `system:unauthenticated`에 권한을 부여하는 것도 매우 위험합니다.

A) rules의 verbs 필드에 원하는 동사만 지정

B) resourceNames 필드 사용

C) namespace 필드로 필터링

D) level을 None으로 설정

**정답**: A

**설명**: Audit Policy의 rules에서 `verbs` 필드를 사용하여 특정 HTTP 동사에 대해서만 로깅할 수 있습니다. 예를 들어 `verbs: ["create", "update", "delete", "patch"]`로 설정하면 변경 작업만 감사 로그에 기록됩니다.

A) `--read-only-port=0`

B) `--disable-readonly=true`

C) `--secure-port=0`

D) `--port=0`

**정답**: A

**설명**: `--read-only-port=0`으로 설정하면 kubelet의 읽기 전용 HTTP 포트(기본 10255)가 비활성화됩니다. 이 포트는 인증 없이 Pod 정보와 메트릭을 노출하므로 비활성화하는 것이 보안상 권장됩니다.

A) 모든 Pod가 default ServiceAccount 사용

B) 각 애플리케이션 전용 ServiceAccount 생성, 필요 최소 권한만 부여

C) cluster-admin을 모든 ServiceAccount에 부여

D) RBAC 대신 파일 기반 접근 제어 사용

**정답**: B

**설명**: 각 워크로드에 맞는 전용 ServiceAccount를 생성하고, 해당 애플리케이션이 실제로 필요한 리소스와 동사만 허용하는 Role을 만들어 바인딩하는 것이 모범 사례입니다. default ServiceAccount를 공유하면 불필요한 권한이 과다 부여될 수 있습니다.

A) 8080으로 설정

B) 0으로 설정하여 비활성화

C) 443으로 변경

D) TLS 인증서 추가

**정답**: B

**설명**: `--insecure-port=0`으로 설정하면 TLS 없이 인증도 거치지 않는 HTTP 포트를 비활성화합니다. Kubernetes 1.20부터 이 플래그는 deprecated되었고 기본값이 0이지만, 명시적으로 0으로 설정하는 것이 CIS Benchmark 권장사항입니다.

A) 모든 사용자에게 노드 접근 허용

B) kubelet이 자신이 실행하는 Pod와 관련된 리소스에만 접근하도록 제한

C) 노드 간 네트워크 통신 암호화

D) 노드의 OS 레벨 접근 제어

**정답**: B

**설명**: Node Authorization 모드는 kubelet이 API 서버에 접근할 때 자신의 노드에서 실행 중인 Pod에 필요한 리소스(Secrets, ConfigMaps, PersistentVolumes 등)에만 접근하도록 제한합니다. `--authorization-mode=Node,RBAC`로 함께 사용하는 것이 권장됩니다.

A) CSR 생성 → approve → CSR 오브젝트 생성 → 인증서 추출

B) 개인키 생성 → CSR 파일 생성 → CSR 오브젝트 생성 → approve → 인증서 추출

C) CA 직접 서명 → kubeconfig 설정

D) ServiceAccount 토큰 사용

**정답**: B

**설명**: 올바른 순서는 1) openssl로 개인키 생성, 2) CSR 파일 생성, 3) base64 인코딩하여 CertificateSigningRequest 오브젝트 생성, 4) `kubectl certificate approve`로 승인, 5) `kubectl get csr -o jsonpath='{.status.certificate}'`로 인증서 추출입니다.

A) 클러스터 인증서 갱신

B) 특정 사용자/ServiceAccount가 특정 작업을 수행할 수 있는지 확인

C) RBAC 규칙 적용

D) 감사 로그 확인

**정답**: B

**설명**: `kubectl auth can-i get pods --namespace default`처럼 사용하여 현재 사용자가 특정 작업을 할 수 있는지 확인합니다. `--as` 플래그로 다른 사용자를 가장하여 확인할 수도 있습니다. RBAC 설정 검증에 매우 유용합니다.

System Hardening (Q23~Q32)

A) `security.alpha.kubernetes.io/apparmor: runtime/default`

B) `container.apparmor.security.beta.kubernetes.io/CONTAINER_NAME: localhost/PROFILE_NAME`

C) `apparmor.kubernetes.io/profile: enforced`

D) `securityContext.appArmorProfile: localhost/custom`

**정답**: B

**설명**: Kubernetes 1.30 이전에는 `container.apparmor.security.beta.kubernetes.io/컨테이너이름: localhost/프로파일이름` annotation으로 AppArmor를 적용했습니다. 1.30부터는 `securityContext.appArmorProfile` 필드를 사용합니다. 프로파일은 노드에 미리 로드되어 있어야 합니다.

A) Pod annotation으로만 설정

B) `securityContext.seccompProfile.type: RuntimeDefault`

C) 별도 CRD 생성 필요

D) Node 레벨에서만 설정 가능

**정답**: B

**설명**: Kubernetes 1.19부터 `securityContext.seccompProfile` 필드로 Seccomp를 설정할 수 있습니다. `type: RuntimeDefault`는 컨테이너 런타임의 기본 Seccomp 프로파일을 사용하며, `type: Localhost`로 사용자 정의 프로파일을 지정할 수도 있습니다.

A) NetworkPolicy

B) RBAC

C) AppArmor, Seccomp

D) PodDisruptionBudget

**정답**: C

**설명**: AppArmor는 MAC(Mandatory Access Control)으로 프로세스가 접근할 수 있는 파일, 네트워크, 기능을 제한합니다. Seccomp는 프로세스가 호출할 수 있는 시스템 콜을 제한합니다. 두 도구 모두 컨테이너 내 프로세스의 OS 레벨 행동을 제한합니다.

A) `kubectl describe node`

B) `ss -tlnp` 또는 `netstat -tlnp`

C) `docker ps`

D) `journalctl -u kubelet`

**정답**: B

**설명**: `ss -tlnp`(소켓 통계) 또는 `netstat -tlnp` 명령어로 현재 노드에서 리스닝 중인 TCP 포트와 해당 프로세스를 확인할 수 있습니다. 불필요한 서비스가 포트를 열고 있다면 비활성화하거나 제거해야 합니다.

A) `securityContext.privileged: false`

B) `securityContext.capabilities.drop: ["ALL"]`

C) `securityContext.runAsRoot: false`

D) `securityContext.allowPrivilegeEscalation: false`

**정답**: B

**설명**: `securityContext.capabilities.drop: ["ALL"]`로 모든 Linux capability를 제거하고, `capabilities.add`로 필요한 capability만 선택적으로 추가하는 것이 모범 사례입니다. `allowPrivilegeEscalation: false`와 함께 사용하면 더욱 강화됩니다.

A) `spec.runtimeClassName: gvisor`

B) `spec.securityContext.runtime: gvisor`

C) annotation으로 설정

D) Node label로 자동 선택

**정답**: A

**설명**: RuntimeClass 오브젝트를 먼저 생성(handler: runsc)한 후, Pod spec의 `runtimeClassName` 필드로 해당 RuntimeClass를 지정합니다. gVisor는 사용자 공간 커널을 구현하여 컨테이너를 샌드박싱하므로 호스트 커널과 격리됩니다.

A) 노드 IAM 역할에 모든 권한 부여

B) Access Key/Secret Key를 Secret에 저장

C) OIDC Provider와 ServiceAccount annotation으로 IAM Role 연결

D) EC2 인스턴스 프로파일만 사용

**정답**: C

**설명**: IRSA(IAM Roles for Service Accounts)는 EKS OIDC Provider를 사용하여 Kubernetes ServiceAccount를 IAM Role과 연결합니다. `eks.amazonaws.com/role-arn` annotation을 ServiceAccount에 추가하면 해당 SA를 사용하는 Pod에만 특정 IAM 권한이 부여됩니다.

A) `securityContext.immutable: true`

B) `securityContext.readOnlyRootFilesystem: true`

C) `securityContext.noWrite: true`

D) `volumeMounts.readOnly: true`

**정답**: B

**설명**: `securityContext.readOnlyRootFilesystem: true`를 설정하면 컨테이너의 루트 파일시스템이 읽기 전용이 됩니다. 공격자가 컨테이너 내부에 악성 파일을 생성하거나 바이너리를 변조하는 것을 방지합니다. 쓰기가 필요한 경로는 emptyDir 볼륨으로 마운트합니다.

A) `securityContext.runAsUser: 0`

B) `securityContext.runAsNonRoot: true`

C) `securityContext.privileged: false`

D) RBAC로 제어

**정답**: B

**설명**: `securityContext.runAsNonRoot: true`를 설정하면 컨테이너가 root(UID 0)로 실행되려 할 때 Kubernetes가 이를 차단합니다. `runAsUser: 1000`처럼 특정 UID를 지정하는 것도 좋은 방법입니다.

A) 커널 공유하는 일반 컨테이너 격리

B) 각 컨테이너/Pod가 경량 VM과 독립 커널로 실행

C) 네트워크 격리만 제공

D) Seccomp 프로파일 기반 격리

**정답**: B

**설명**: Kata Containers는 각 컨테이너(또는 Pod)를 경량 VM 위에서 실행합니다. 각 워크로드가 독립적인 커널을 가지므로 커널 취약점을 통한 컨테이너 탈출이 극도로 어렵습니다. gVisor와 달리 실제 Linux 커널을 사용합니다.

Minimizing Microservice Vulnerabilities (Q33~42)

A) 차이 없음

B) enforce는 정책 위반 Pod를 거부, warn은 경고만 표시하고 허용

C) warn이 더 엄격

D) enforce는 기존 Pod에도 소급 적용

**정답**: B

**설명**: PSA의 세 가지 모드 중 `enforce`는 정책을 위반하는 Pod 생성을 거부합니다. `warn`은 위반 시 경고 메시지를 반환하지만 Pod는 생성됩니다. `audit`는 감사 로그에 기록하지만 역시 Pod는 허용됩니다.

A) 동일한 정책 언어 사용

B) Kubernetes admission webhook으로 동작하여 정책을 강제

C) 런타임 모니터링 도구

D) 네트워크 정책 관리

**정답**: B

**설명**: OPA Gatekeeper와 Kyverno 모두 Kubernetes ValidatingAdmissionWebhook으로 동작하여 리소스 생성/수정 시 정책을 검사하고 위반 시 거부합니다. Gatekeeper는 Rego 언어를, Kyverno는 YAML 기반 정책을 사용한다는 차이가 있습니다.

A) 성능 향상

B) 서비스 간 통신의 양방향 인증 및 암호화

C) 외부 트래픽 차단

D) 데이터베이스 암호화

**정답**: B

**설명**: mTLS는 클라이언트와 서버 모두 인증서로 서로를 인증합니다. Istio에서 `PeerAuthentication` 리소스로 STRICT mTLS를 설정하면 서비스 간 모든 통신이 암호화되고, 인증된 서비스만 통신할 수 있어 측면 이동(lateral movement) 공격을 방지합니다.

A) etcd at-rest 암호화 활성화

B) Vault나 Sealed Secrets 사용

C) Secrets를 Git 저장소에 평문으로 저장

D) RBAC로 Secrets 접근 제한

**정답**: C

**설명**: Secrets를 Git에 평문으로 저장하는 것은 매우 위험합니다. 올바른 방법은 etcd 암호화, Bitnami Sealed Secrets(암호화된 SealedSecret을 Git에 저장), HashiCorp Vault(동적 시크릿 관리), AWS Secrets Manager 연동 등입니다.

A) `runAsNonRoot: true`

B) `seccompProfile.type: RuntimeDefault`

C) `privileged: true`

D) `capabilities.drop: ["ALL"]`

**정답**: C

**설명**: Restricted PSS는 가장 엄격한 프로파일로 `privileged: true`, hostNetwork, hostPID, hostIPC 사용 금지, 특정 capability 추가 금지, runAsNonRoot 필수 등을 요구합니다. `privileged: true`는 Privileged PSS에서만 허용됩니다.

A) 성능 문제로 인해, RuntimeClass로 대체

B) 복잡성과 권한 상승 위험으로 인해, Pod Security Admission으로 대체

C) 기능 부족으로 인해, OPA로 대체

D) etcd 호환성 문제

**정답**: B

**설명**: PSP는 Kubernetes 1.21에서 deprecated, 1.25에서 제거되었습니다. PSP를 사용하려면 서비스에 ClusterRole을 통한 PSP use 권한이 필요했는데, 이 과정에서 권한 상승이 발생할 수 있었고 설정이 복잡했습니다. 대체재는 Pod Security Admission(PSA)이며, OPA Gatekeeper나 Kyverno도 사용됩니다.

A) gVisor

B) Kata Containers

C) Firecracker

D) Calico

**정답**: D

**설명**: gVisor, Kata Containers, Firecracker는 컨테이너 격리를 강화하는 샌드박싱 기술입니다. Calico는 CNI 네트워크 플러그인으로 네트워크 정책을 구현하는 도구이며 샌드박싱 기술이 아닙니다.

A) 인증서 자동 갱신

B) 서비스 간 접근 제어(누가 누구에게 요청 가능한지 정의)

C) 트래픽 로드 밸런싱

D) 컨테이너 이미지 스캔

**정답**: B

**설명**: Istio `AuthorizationPolicy`는 서비스 메시 내에서 L7 수준의 접근 제어를 구현합니다. 특정 서비스, 경로, 메서드에 대해 어떤 서비스/사용자가 접근할 수 있는지 정의합니다. mTLS와 함께 사용하면 Zero Trust 네트워킹을 구현할 수 있습니다.

A) 성능 저하

B) 프로세스 환경에 노출되어 `proc/PID/environ`으로 읽히거나 로그에 출력될 위험

C) 크기 제한

D) 타입 제한

**정답**: B

**설명**: 환경 변수는 프로세스의 `/proc/PID/environ`을 통해 읽을 수 있고, 애플리케이션이 실수로 환경 변수를 로그에 출력할 수 있습니다. 볼륨 마운트 방식이 더 안전하며, 특히 Vault Agent Injector나 CSI Secret Store 방식을 권장합니다.

A) 방화벽만 사용

B) mTLS + RBAC + NetworkPolicy + PSA 조합

C) VPN만 사용

D) 물리적 네트워크 분리

**정답**: B

**설명**: Zero Trust는 "신뢰하지 말고 항상 검증하라"는 원칙입니다. Kubernetes에서는 mTLS(서비스 간 인증), RBAC(최소 권한), NetworkPolicy(네트워크 마이크로세그멘테이션), PSA(워크로드 보안 표준)를 조합하여 구현합니다.

Supply Chain Security (Q43~52)

A) `trivy scan IMAGE_NAME`

B) `trivy image IMAGE_NAME`

C) `trivy check IMAGE_NAME`

D) `trivy docker IMAGE_NAME`

**정답**: B

**설명**: `trivy image nginx:latest`처럼 `trivy image` 서브커맨드를 사용합니다. CVE 데이터베이스를 기반으로 이미지의 OS 패키지, 언어별 의존성 등의 취약점을 스캔합니다. `--severity HIGH,CRITICAL`로 심각도 필터링도 가능합니다.

A) 이미지를 자동으로 최신 버전으로 업데이트

B) 외부 웹훅 서비스에 이미지 허용 여부를 질의

C) 이미지 취약점 자동 수정

D) 이미지 크기 제한

**정답**: B

**설명**: ImagePolicyWebhook은 Pod 생성 시 외부 웹훅 서비스에 이미지 사용 허용 여부를 질의합니다. 웹훅 서비스는 이미지 스캔 결과, 서명 검증, 레지스트리 정책 등을 기반으로 허용/거부를 응답합니다.

A) `cosign sign --key cosign.key IMAGE_DIGEST`

B) `cosign create-signature IMAGE`

C) `docker sign IMAGE`

D) `kubectl sign image IMAGE`

**정답**: A

**설명**: `cosign sign --key cosign.key IMAGE@sha256:DIGEST`로 이미지에 서명합니다. 서명은 OCI 레지스트리에 별도 태그로 저장됩니다. `cosign verify --key cosign.pub IMAGE`로 검증하며, Kyverno 정책으로 서명된 이미지만 허용하도록 강제할 수 있습니다.

A) 소프트웨어 라이선스 목록

B) 소프트웨어를 구성하는 모든 컴포넌트, 라이브러리, 의존성 목록

C) 소프트웨어 비용 명세서

D) 소프트웨어 배포 계획서

**정답**: B

**설명**: SBOM은 소프트웨어에 포함된 모든 오픈소스 및 독점 컴포넌트, 버전, 라이선스, 취약점 정보를 담은 목록입니다. CycloneDX, SPDX 형식이 표준으로 사용됩니다. 공급망 공격 방지와 취약점 추적에 필수적입니다.

A) 이미지 크기가 작아 빌드 속도 향상

B) 쉘, 패키지 관리자 등 불필요한 도구 제거로 공격 표면 최소화

C) 무료로 사용 가능

D) CI/CD 파이프라인 통합 용이

**정답**: B

**설명**: Distroless 이미지는 애플리케이션 실행에 필요한 런타임만 포함하고 쉘(/bin/sh), 패키지 관리자, 불필요한 유틸리티가 없습니다. 공격자가 컨테이너에 침입해도 활용할 수 있는 도구가 없어 피해를 최소화할 수 있습니다.

A) RBAC 규칙 추가

B) webhook 서비스가 admission review 요청을 검사하고 거부 응답

C) NetworkPolicy 설정

D) Pod 삭제 컨트롤러 배포

**정답**: B

**설명**: ValidatingWebhookConfiguration은 리소스 생성/수정 시 외부 webhook 서비스에 AdmissionReview 요청을 보냅니다. webhook 서비스는 요청을 검사하여 `allowed: false`와 메시지를 반환하면 Kubernetes API 서버가 리소스 생성을 거부합니다.

A) latest 태그가 deprecated됨

B) 재현성 부재, 어떤 이미지 버전이 실행 중인지 알 수 없음

C) 레지스트리 용량 낭비

D) 빌드 속도 저하

**정답**: B

**설명**: latest 태그는 변경 가능(mutable)하여 동일한 태그로 다른 이미지가 푸시될 수 있습니다. 이로 인해 배포 재현성이 없고, 보안 취약점이 있는 이미지가 latest로 배포될 수 있습니다. 항상 SHA256 다이제스트나 고정된 버전 태그를 사용해야 합니다.

A) MutatePolicy

B) ClusterPolicy with validate rule

C) GeneratePolicy

D) SyncPolicy

**정답**: B

**설명**: Kyverno `ClusterPolicy`의 `validate` 규칙으로 이미지 태그가 latest인 경우를 거부할 수 있습니다. `deny` 조건에서 이미지 태그를 검사하고 위반 시 `message`와 함께 거부합니다. `mutate` 규칙으로 이미지를 자동 변환할 수도 있습니다.

A) SolarWinds 해킹

B) 악성 npm 패키지 배포

C) DDoS 공격

D) 의존성 혼동 공격(Dependency Confusion)

**정답**: C

**설명**: 공급망 공격은 소프트웨어 개발/배포 파이프라인의 취약점을 이용합니다. SolarWinds 빌드 서버 침해, 악성 npm/PyPI 패키지, Dependency Confusion(사설 패키지명으로 공개 패키지 배포)이 대표적 예시입니다. DDoS는 가용성 공격으로 공급망 공격이 아닙니다.

A) ServiceAccount

B) imagePullSecret

C) ConfigMap

D) PersistentVolumeClaim

**정답**: B

**설명**: 프라이빗 레지스트리 인증을 위해 `docker-registry` 타입의 Secret을 생성하고, Pod spec의 `imagePullSecrets`에 참조하거나 ServiceAccount의 `imagePullSecrets`에 추가합니다. 이렇게 하면 해당 SA를 사용하는 모든 Pod가 자동으로 인증됩니다.

Monitoring, Logging and Runtime Security (Q53~55)

A) `evt.type=connect and fd.type=ipv4`

B) `evt.type=execve and container.id!=host and proc.name in (sh, bash, zsh)`

C) `evt.type=open and fd.name contains /etc/passwd`

D) `evt.type=write and fd.name startswith /tmp`

**정답**: B

**설명**: Falco에서 `execve` 이벤트 타입은 새 프로세스 실행을 의미합니다. `container.id!=host`는 컨테이너 내부를 의미하고, `proc.name in (sh, bash, zsh)`는 쉘 프로세스를 필터링합니다. 기본 제공 규칙 `Terminal shell in container`가 이 패턴을 사용합니다.

A) audit policy에서 해당 규칙을 제거

B) 해당 리소스/namespace/동사에 level: None 규칙을 먼저 작성

C) kube-system namespace 삭제

D) Secrets 타입 변경

**정답**: B

**설명**: Audit Policy는 규칙을 순서대로 평가하여 첫 번째 매칭 규칙을 적용합니다. `level: None`으로 특정 조건을 건너뛰려면 해당 규칙을 다른 규칙보다 먼저(상위에) 작성해야 합니다. 예를 들어 kube-system secrets의 get 요청을 제외할 때는 `level: None`, `resources: secrets`, `namespaces: kube-system`, `verbs: get` 규칙을 파일 상단에 작성합니다.

A) 즉시 삭제 후 재배포

B) 증거 수집(로그, 포렌식) → Pod 격리(NetworkPolicy) → 침해 범위 파악 → 수정 및 재배포

C) 노드 재시작

D) 클러스터 전체 재배포

**정답**: B

**설명**: 침해 대응의 올바른 순서는 1) 증거 보존(로그 수집, 메모리 덤프), 2) 추가 피해 방지를 위해 NetworkPolicy로 해당 Pod의 네트워크 격리, 3) 침해 경로와 범위 파악, 4) 취약점 수정 후 새 이미지 빌드 및 배포입니다. 즉시 삭제하면 포렌식 증거를 잃게 됩니다.

4. 실기 시나리오 (P1~P10)

P1. NetworkPolicy로 Pod 격리 설정

특정 namespace의 Pod만 DB에 접근 허용하는 NetworkPolicy 작성

cat <<EOF | kubectl apply -f -

apiVersion: networking.k8s.io/v1

kind: NetworkPolicy

metadata:

name: db-allow-app-only

namespace: production

spec:

podSelector:

matchLabels:

app: database

policyTypes:

- Ingress

ingress:

- from:

- namespaceSelector:

matchLabels:

name: production

podSelector:

matchLabels:

app: backend

ports:

- protocol: TCP

port: 5432

EOF

P2. ServiceAccount 보안 강화

1. 전용 ServiceAccount 생성 (automount 비활성화)

kubectl create serviceaccount app-sa -n default

kubectl patch serviceaccount app-sa -n default -p '{"automountServiceAccountToken": false}'

2. 필요한 권한만 부여하는 Role 생성

cat <<EOF | kubectl apply -f -

apiVersion: rbac.authorization.k8s.io/v1

kind: Role

metadata:

name: app-role

namespace: default

rules:

- apiGroups: [""]

resources: ["configmaps"]

verbs: ["get", "list"]

EOF

3. RoleBinding

kubectl create rolebinding app-binding \

--role=app-role \

--serviceaccount=default:app-sa \

-n default

4. 권한 확인

kubectl auth can-i get configmaps \

--as=system:serviceaccount:default:app-sa \

-n default

P3. etcd 암호화 설정

1. 암호화 키 생성

head -c 32 /dev/urandom | base64

2. EncryptionConfiguration 작성

cat <<EOF > /etc/kubernetes/encryption-config.yaml

apiVersion: apiserver.config.k8s.io/v1

kind: EncryptionConfiguration

resources:

- resources:

- secrets

providers:

- aescbc:

keys:

- name: key1

secret: <BASE64_32BYTE_KEY>

- identity: {}

EOF

3. kube-apiserver manifest 수정 (/etc/kubernetes/manifests/kube-apiserver.yaml)

--encryption-provider-config=/etc/kubernetes/encryption-config.yaml 추가

4. 기존 Secrets를 새로 암호화 (re-encrypt)

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

5. etcd에서 직접 확인 (암호화되어 읽을 수 없어야 함)

ETCDCTL_API=3 etcdctl \

--endpoints=https://127.0.0.1:2379 \

--cacert=/etc/kubernetes/pki/etcd/ca.crt \

--cert=/etc/kubernetes/pki/etcd/server.crt \

--key=/etc/kubernetes/pki/etcd/server.key \

get /registry/secrets/default/my-secret

P4. AppArmor 프로파일 적용

1. 노드에 AppArmor 프로파일 확인

ssh worker-node-1 "aa-status"

2. 커스텀 프로파일 파일 생성 (노드에서)

cat <<EOF > /etc/apparmor.d/k8s-custom-profile

#include <tunables/global>

profile k8s-custom-profile flags=(attach_disconnected) {

#include <abstractions/base>

file,

deny /etc/shadow r,

deny /proc/** w,

}

EOF

3. 프로파일 로드

apparmor_parser -r /etc/apparmor.d/k8s-custom-profile

4. Pod에 AppArmor 적용 (Kubernetes 1.30 이전)

cat <<EOF | kubectl apply -f -

apiVersion: v1

kind: Pod

metadata:

name: secured-pod

annotations:

container.apparmor.security.beta.kubernetes.io/app: localhost/k8s-custom-profile

spec:

containers:

- name: app

image: nginx:alpine

EOF

P5. Falco 규칙 커스터마이징

/etc/falco/rules.d/custom-rules.yaml

- rule: Detect Shell in Container

desc: Alert when a shell is spawned in a container

condition: >

spawned_process and

container and

proc.name in (shell_binaries)

output: >

Shell spawned in container

(user=%user.name container=%container.name

image=%container.image.repository proc=%proc.name

parent=%proc.pname cmdline=%proc.cmdline)

priority: WARNING

tags: [container, shell, cks]

- rule: Sensitive File Access

desc: Detect access to sensitive files

condition: >

open_read and

(fd.name in (/etc/shadow, /etc/sudoers) or

fd.name startswith /root/.ssh)

output: >

Sensitive file accessed

(user=%user.name file=%fd.name

container=%container.name proc=%proc.name)

priority: CRITICAL

tags: [filesystem, sensitive, cks]

Falco 재시작 후 규칙 확인

systemctl restart falco

falco --list | grep "Detect Shell"

P6. Pod Security Admission 설정

namespace에 PSA 레이블 설정

kubectl label namespace production \

pod-security.kubernetes.io/enforce=restricted \

pod-security.kubernetes.io/enforce-version=latest \

pod-security.kubernetes.io/warn=restricted \

pod-security.kubernetes.io/warn-version=latest \

pod-security.kubernetes.io/audit=restricted \

pod-security.kubernetes.io/audit-version=latest

Restricted PSS 준수 Pod 예시

cat <<EOF | kubectl apply -f -

apiVersion: v1

kind: Pod

metadata:

name: restricted-pod

namespace: production

spec:

securityContext:

runAsNonRoot: true

runAsUser: 1000

seccompProfile:

type: RuntimeDefault

containers:

- name: app

image: nginx:alpine

securityContext:

allowPrivilegeEscalation: false

readOnlyRootFilesystem: true

capabilities:

drop: ["ALL"]

volumeMounts:

- name: tmp

mountPath: /tmp

- name: var-cache

mountPath: /var/cache/nginx

- name: var-run

mountPath: /var/run

volumes:

- name: tmp

emptyDir: {}

- name: var-cache

emptyDir: {}

- name: var-run

emptyDir: {}

EOF

P7. Trivy를 사용한 이미지 스캔

이미지 스캔 (HIGH, CRITICAL만)

trivy image --severity HIGH,CRITICAL nginx:latest

JSON 형식으로 출력

trivy image -f json -o scan-result.json nginx:latest

파일시스템 스캔

trivy fs --security-checks vuln,secret /path/to/project

Kubernetes cluster 스캔

trivy k8s --report summary cluster

CI/CD 파이프라인에서 취약점 발견 시 실패처리

trivy image --exit-code 1 --severity CRITICAL myapp:latest

P8. Audit Policy 설정

/etc/kubernetes/audit-policy.yaml

apiVersion: audit.k8s.io/v1

kind: Policy

rules:

kube-system의 ServiceAccount token 요청은 기록 안 함

- level: None

resources:

- group: ''

resources: ['secrets']

namespaces: ['kube-system']

verbs: ['get']

Secrets에 대한 모든 접근 상세 기록

- level: RequestResponse

resources:

- group: ''

resources: ['secrets']

Pod 변경사항 기록

- level: Request

resources:

- group: ''

resources: ['pods']

verbs: ['create', 'update', 'patch', 'delete']

그 외 모든 요청 메타데이터만 기록

- level: Metadata

omitStages:

- RequestReceived

kube-apiserver에 audit policy 적용 (manifest 수정)

--audit-log-path=/var/log/kubernetes/audit.log

--audit-policy-file=/etc/kubernetes/audit-policy.yaml

--audit-log-maxage=30

--audit-log-maxbackup=10

--audit-log-maxsize=100

P9. gVisor RuntimeClass 설정

1. containerd에 gVisor 설정 확인 (/etc/containerd/config.toml)

[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]

runtime_type = "io.containerd.runsc.v1"

2. RuntimeClass 생성

cat <<EOF | kubectl apply -f -

apiVersion: node.k8s.io/v1

kind: RuntimeClass

metadata:

name: gvisor

handler: runsc

EOF

3. gVisor를 사용하는 Pod 배포

cat <<EOF | kubectl apply -f -

apiVersion: v1

kind: Pod

metadata:

name: sandboxed-pod

spec:

runtimeClassName: gvisor

containers:

- name: app

image: nginx:alpine

EOF

4. 샌드박싱 확인

kubectl exec sandboxed-pod -- uname -r

gVisor 커널 버전이 표시됨

P10. Cosign을 사용한 이미지 서명 및 검증

1. 키 쌍 생성

cosign generate-key-pair

2. 이미지 빌드 및 push

docker build -t registry.example.com/myapp:v1.0 .

docker push registry.example.com/myapp:v1.0

3. 이미지 서명

cosign sign --key cosign.key registry.example.com/myapp:v1.0

4. 서명 검증

cosign verify --key cosign.pub registry.example.com/myapp:v1.0

5. Kyverno 정책으로 서명된 이미지만 허용

cat <<EOF | kubectl apply -f -

apiVersion: kyverno.io/v1

kind: ClusterPolicy

metadata:

name: verify-image-signature

spec:

validationFailureAction: Enforce

rules:

- name: verify-cosign

match:

any:

- resources:

kinds: ["Pod"]

verifyImages:

- imageReferences: ["registry.example.com/*"]

attestors:

- entries:

- keys:

publicKeys: |-

-----BEGIN PUBLIC KEY-----

-----END PUBLIC KEY-----

EOF

5. 시험 팁

- **시험 환경**: 브라우저 터미널에서 `kubectl`, `crictl`, `kubeadm`, `openssl`, `falco`, `trivy`, `cosign` 등 사용 가능

- **빠른 명령어**: `kubectl config use-context` 로 문제별 컨텍스트 전환 필수

- **북마크**: killer.sh, Kubernetes 공식 문서 등 허용된 리소스 적극 활용

- **우선순위**: 배점이 높은 문제부터 풀고 어려운 문제는 나중에

- **검증**: 설정 변경 후 항상 `kubectl get`, `kubectl describe`로 검증

현재 단락 (1/606)

CKS(Certified Kubernetes Security Specialist)는 CNCF와 Linux Foundation이 제공하는 고급 Kubernetes 보안 자격증입니다.

작성 글자: 0원문 글자: 21,559작성 단락: 0/606