LabHub
배우기 러닝패스 코스

CKS — 쿠버네티스 보안 전문가 · 모의고사 · 실습

CKS 모의고사 B

LabHub 에서 이어서 보기

목표

B 회차입니다. A 회차와 겹치는 문제가 하나도 없습니다. 같은 도메인을
같은 비율로 묻지만 확인하는 역량이 모두 다릅니다. A 를 풀어 본 뒤에 이어서
치르면 어느 도메인이 아직 약한지가 드러납니다.

실제 CKS 와 같은 조건에서 과제 17개를 120분 안에 풉니다. 합격선은 67% 이고
부분 점수제이므로, 17개 중 12개를 통과하면 완료로 처리됩니다.

모의고사입니다. 힌트와 정답지를 보지 말고 먼저 끝까지 풀어 보십시오.
막힌 과제는 표시해 두고 넘어갔다가 남은 시간에 돌아오는 편이 낫습니다.
채점은 언제든 눌러도 되고, 여러 번 눌러도 결과가 달라지지 않습니다.

왜 중요한가

CKS 는 CKA 합격이 선수 조건인 유일한 시험입니다. 쿠버네티스를 다루는 손은
이미 갖췄다고 전제하므로, 문제는 "무엇을 만드세요" 보다 "이 설정의 무엇이
위험한지 찾아 고치세요" 쪽에 가깝습니다. 방어와 진단이 시험 대상이고,
공격 기법은 다루지 않습니다.

이 회차는 특히 경계를 좁히는 방법을 묻습니다. 권한을 이름 하나로 좁히고,
토큰에 대상과 수명을 붙이고, 규칙은 한 번만 쓰되 효력은 한 네임스페이스로
자릅니다. 넓게 열어 두고 나중에 좁히는 일은 실무에서 거의 일어나지 않으므로,
처음부터 좁게 여는 손이 곧 실력입니다.

시험 환경 (실제 시험에서 확인된 사실)

이 모의고사 환경에서 다른 점

이 실습의 클러스터는 파드 안에서 도는 1인용 클러스터입니다. kube-apiserver 는
진짜라서 매니페스트, RBAC, 파드 보안 승인, 승인 정책은 **실제로 동작하고 실제로
거부합니다.** 다만 컨테이너를 실제로 돌리는 런타임이 없으므로 다음 세 가지는
확인할 수 없습니다.

나머지는 전부 살아 있는 클러스터에서 다시 계산해 채점합니다. 권한은
kubectl auth can-i 로, 승인 정책과 파드 보안 승인은 서버 dry-run 으로 그
순간의 판정을 다시 물어봅니다.

단계

Cluster Setup

1. 네임스페이스 staging 을 만들고, 그 안에서 app=web 이 아니라 app=api
라벨이 붙은 파드에 적용되는 NetworkPolicy api-allow 를 만드십시오.
인그레스는 env=frontend 라벨이 붙은 네임스페이스 안의 role=web 라벨이
붙은 파드에서 오는 TCP 8080 만 허용하고, 나머지 인그레스는 모두 막습니다.
이그레스는 UDP 53 과 TCP 53 만 허용하고 나머지는 모두 막습니다.
2. /usr/local/bin/kubectl/usr/local/bin/helm 의 SHA-256 해시를
sha256sum 출력 형식 그대로 /root/exam/verify/binaries.sha256
저장하십시오. 경로는 절대 경로여야 하고, sha256sum -c 로 검증했을 때
두 항목 모두 통과해야 합니다.
3. /root/exam/kubelet/config.yaml 에 kubelet 구성을 작성하십시오.
apiVersionkubelet.config.k8s.io/v1beta1, kind
KubeletConfiguration 입니다. 익명 접근을 끄고, 웹훅 인증을 켜고, 인가
방식을 Webhook 으로 하고, 인증 없는 읽기 전용 포트를 닫고, 커널 기본값
보호를 켜십시오.

Cluster Hardening

4. 네임스페이스 staging 에서 사용자 ci-deployer 가 Deployment web 하나만
get, patch, update 할 수 있게 Role web-deployer 와 RoleBinding
ci-deployer-web 을 만드십시오. 같은 네임스페이스의 다른 Deployment 는
건드릴 수 없어야 하고, Deployment 목록을 볼 수도 없어야 합니다.
5. 네임스페이스 staging 에 서비스 계정 agent 를 만들고 파드 collector
만드십시오. 파드는 서비스 계정 agent 를 쓰되 기본 토큰 자동 마운트는
끄고, 대신 projected 볼륨 token 으로 대상이 vault 이고 유효 기간이
3600초인 서비스 계정 토큰을 파일 이름 token 으로 발급받아
/var/run/secrets/vault 에 마운트하십시오. 컨테이너 이름은 app 입니다.
6. ClusterRole namespace-reader 를 만들어 코어 그룹의 pods, services,
configmapsget, list, watch 할 수 있게 하십시오. 그리고 사용자
oncall네임스페이스 staging 안에서만 그 권한을 갖도록 RoleBinding
oncall-reader 를 만드십시오. 다른 네임스페이스에서는 아무것도 읽을 수
없어야 하고, staging 안에서도 시크릿은 읽을 수 없어야 합니다.

System Hardening

7. /root/exam/seccomp/net-deny.json 에 seccomp 프로파일을 작성하십시오.
기본 동작은 SCMP_ACT_LOG 이고, socketconnect 시스템 콜은
SCMP_ACT_ERRNO 로 막아야 합니다. 그리고 네임스페이스 staging 에 파드
sensor 를 만들되, 파드 수준에는 RuntimeDefault 프로파일을 두고
컨테이너 app 에서만 이 프로파일을 Localhost 방식으로
profiles/net-deny.json 경로에서 쓰게 하십시오.
8. /root/exam/sudoers.d/deploy 에 sudo 규칙을 작성하십시오. 사용자 deploy
가 비밀번호를 묻지 않고 /usr/bin/systemctl restart kubelet 하나만 root 로
실행할 수 있어야 합니다. 명령 자리에 ALL 을 쓴 규칙은 두지 마십시오.
파일은 visudo -cf 의 문법 검사를 통과해야 합니다.

Minimize Microservice Vulnerabilities

9. 네임스페이스 payments 를 만들고 파드 보안 승인을 단계적으로 거십시오.
enforcebaseline 이고 버전은 v1.31 로 고정합니다. audit
warnrestricted 이고 버전은 latest 입니다. 결과적으로 baseline
을 어기는 파드는 실제로 거부되고, restricted 만 어기는 파드는 경고를
받으면서 만들어져야 합니다.
10. 네임스페이스 payments 에 시크릿 db-cred 를 만드십시오. 타입은 기본
(Opaque)이고 키는 usernamepassword 입니다. 그리고 파드
reporter 를 만들어 이 시크릿을 볼륨 cred/etc/db 에 읽기 전용으로
마운트하되 파일 권한은 8진수 0400 이어야 합니다. 시크릿 값을 환경
변수로는 넣지 마십시오. 컨테이너 이름은 app 입니다.
11. /root/exam/encryption/config.yaml 에 저장 시 암호화 구성을 작성하십시오.
apiVersionapiserver.config.k8s.io/v1, kind
EncryptionConfiguration 입니다. 암호화 대상은 secrets 이고, 제공자는
aescbc 가 첫 번째, identity 가 마지막이어야 합니다. aescbc 의 키는
이름을 갖고 값은 32바이트를 base64 로 적은 것이어야 합니다.

Supply Chain Security

12. 네임스페이스 supply 를 만들고, 레지스트리 registry.internal 에 사용자
deployer 로 접근하는 자격 증명을 시크릿 regcred 로 만드십시오. 서비스
계정 puller 가 그 시크릿으로 이미지를 내려받게 연결하고, Deployment
catalog 가 그 서비스 계정을 쓰게 하십시오. 컨테이너 이름은 app 이고
이미지는 registry.internal/catalog:1.4.2 입니다.
13. 네임스페이스 supply 에서 움직이는 태그를 막으십시오.
ValidatingAdmissionPolicy no-latest-tag
ValidatingAdmissionPolicyBinding no-latest-tag 를 만들고, 파드의
모든 컨테이너와 모든 초기화 컨테이너의 이미지가 :latest 로 끝나지
않을 것을 요구하게 하십시오. 바인딩의 validationActionsDeny 이고
적용 범위는 네임스페이스 supply 뿐입니다. 다른 네임스페이스는 영향을
받으면 안 됩니다.
14. /root/exam/imagepolicy/admission-config.yaml 에 승인 구성 파일을
작성하십시오. apiVersionapiserver.config.k8s.io/v1, kind
AdmissionConfiguration 이고, 플러그인은 ImagePolicyWebhook 하나입니다.
그 설정의 imagePolicykubeConfigFile
/etc/kubernetes/imagepolicy/kubeconfig.yaml 을 적고, allowTTL 50,
denyTTL 50, retryBackoff 500 을 두며, 웹훅에 닿지 못했을 때 이미지가
허용되지 않도록 defaultAllow 를 거짓으로 두십시오.

Monitoring, Logging and Runtime Security

15. /root/exam/falco/rules.yaml 에 런타임 탐지 규칙을 작성하십시오. 파일은
항목들의 목록이고, 그 안에 trusted_writers 라는 list 항목과
Write below etc 라는 rule 항목이 하나씩 있어야 합니다. 목록에는
항목이 최소 하나 있어야 합니다. 규칙의 priorityWARNING 이고,
desctags 가 비어 있으면 안 되며, condition 에는 open_write,
/etc, trusted_writers 가 모두 나와야 하고, output 에는
%proc.name%fd.name 이 있어야 합니다.
16. /root/exam/audit/quiet-policy.yaml 에 감사 정책을 작성하십시오.
apiVersionaudit.k8s.io/v1, kindPolicy 이며 규칙은 정확히
네 개이고 순서가 중요합니다. 첫째, 사용자 system:kube-proxywatch
가 코어 그룹의 endpointsservices 에 닿는 것을 None 으로
버립니다. 둘째, 그룹 system:authenticated 의 비자원 경로 /api*
/version 접근을 None 으로 버립니다. 셋째, 네임스페이스 payments
코어 그룹 secretsRequestResponse 로 남깁니다. 넷째, 대상을 적지
않은 Metadata 규칙으로 나머지 전부를 받습니다.
17. 네임스페이스 runtime 을 만들고, 그 안에서 만들어지는 파드의 모든
컨테이너가 readOnlyRootFilesystem: true 를 갖도록 강제하십시오.
ValidatingAdmissionPolicy immutable-root
ValidatingAdmissionPolicyBinding immutable-root 를 만들고, 바인딩의
validationActionsDeny 이며 적용 범위는 네임스페이스 runtime
뿐입니다. 다른 네임스페이스는 영향을 받으면 안 됩니다.

참고

단계 17개

  1. 두 셀렉터를 함께 둔 허용 목록
  2. 배포 전 이진 파일 검증
  3. kubelet 구성 강화
  4. 이름 하나로 좁힌 권한
  5. 대상과 수명이 정해진 토큰
  6. 규칙은 한 번, 효력은 한 네임스페이스
  7. 컨테이너 수준 seccomp 덮어쓰기
  8. 호스트 계정 권한 최소화
  9. 단계적으로 올리는 파드 보안 승인
  10. 시크릿은 파일로만
  11. 저장 시 암호화 구성
  12. 사설 레지스트리 자격 증명
  13. 움직이는 태그 차단
  14. 이미지 정책 웹훅 구성
  15. 런타임 탐지 규칙
  16. 감사 로그에서 잡음 걷어내기
  17. 읽기 전용 루트를 승인 단계에서 강제