LabHub
배우기 러닝패스 코스

CKS — Kubernetes Security Specialist

CKS Mock Exam 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, kindKubeletConfiguration 입니다. 익명 접근을 끄고, 웹훅 인증을 켜고, 인가 방식을 Webhook 으로 하고, 인증 없는 읽기 전용 포트를 닫고, 커널 기본값 보호를 켜십시오.

Cluster Hardening

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

System Hardening

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

Minimize Microservice Vulnerabilities

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

Supply Chain Security

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

Monitoring, Logging and Runtime Security

  1. /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 이 있어야 합니다.
  2. /root/exam/audit/quiet-policy.yaml 에 감사 정책을 작성하십시오. apiVersionaudit.k8s.io/v1, kindPolicy 이며 규칙은 정확히 네 개이고 순서가 중요합니다. 첫째, 사용자 system:kube-proxywatch 가 코어 그룹의 endpointsservices 에 닿는 것을 None 으로 버립니다. 둘째, 그룹 system:authenticated 의 비자원 경로 /api*/version 접근을 None 으로 버립니다. 셋째, 네임스페이스 payments 의 코어 그룹 secretsRequestResponse 로 남깁니다. 넷째, 대상을 적지 않은 Metadata 규칙으로 나머지 전부를 받습니다.
  3. 네임스페이스 runtime 을 만들고, 그 안에서 만들어지는 파드의 모든 컨테이너가 readOnlyRootFilesystem: true 를 갖도록 강제하십시오. ValidatingAdmissionPolicy immutable-root 와 ValidatingAdmissionPolicyBinding immutable-root 를 만들고, 바인딩의 validationActionsDeny 이며 적용 범위는 네임스페이스 runtime 뿐입니다. 다른 네임스페이스는 영향을 받으면 안 됩니다.

참고

두 셀렉터를 함께 둔 허용 목록

네임스페이스 staging 을 만들고, app=api 라벨이 붙은 파드에 적용되는 NetworkPolicy api-allow 를 만드십시오. 인그레스는 env=frontend 라벨이 붙은 네임스페이스 안의 role=web 라벨이 붙은 파드에서 오는 TCP 8080 만 허용하고, 나머지 인그레스는 모두 막습니다. 이그레스는 UDP 53 과 TCP 53 만 허용하고 나머지는 모두 막습니다.

from 항목 하나 안에 namespaceSelector 와 podSelector 를 함께 적으면 두 조건을 모두 만족하는 파드만 골라집니다. 두 항목으로 나누어 적으면 둘 중 하나만 만족해도 열리므로 범위가 넓어집니다. policyTypes 에 Ingress 와 Egress 를 모두 적어야 이그레스도 통제됩니다. 이그레스 규칙에 ports 만 적고 to 를 적지 않으면 목적지는 제한하지 않으면서 포트만 여는 뜻이 됩니다.

배포 전 이진 파일 검증

/usr/local/bin/kubectl/usr/local/bin/helm 의 SHA-256 해시를 sha256sum 출력 형식 그대로 /root/exam/verify/binaries.sha256 에 저장하십시오. 경로는 절대 경로여야 하고, sha256sum -c 로 검증했을 때 두 항목 모두 통과해야 합니다.

sha256sum 의 출력이 그대로 sha256sum -c 의 입력 형식입니다. 파일 여러 개를 한 번에 주면 줄이 여러 개 나옵니다. 손으로 해시를 옮겨 적으면 한 글자만 달라도 검증이 실패하므로 출력을 리다이렉션으로 그대로 저장하십시오. 상대 경로로 적으면 검증할 때 작업 디렉터리에 따라 파일을 찾지 못합니다.

kubelet 구성 강화

/root/exam/kubelet/config.yaml 에 kubelet 구성을 작성하십시오. apiVersionkubelet.config.k8s.io/v1beta1, kindKubeletConfiguration 입니다. 익명 접근을 끄고, 웹훅 인증을 켜고, 인가 방식을 Webhook 으로 하고, 인증 없는 읽기 전용 포트를 닫고, 커널 기본값 보호를 켜십시오.

익명 접근과 웹훅 인증은 authentication 아래에 따로 있고, 인가 방식은 authorization.mode 입니다. 인가를 AlwaysAllow 로 두면 인증을 아무리 조여도 누구나 무엇이든 할 수 있습니다. 인증 없는 읽기 포트는 readOnlyPort 이고 닫는 값은 0 입니다. 커널 기본값 보호는 protectKernelDefaults 이며, kubelet 이 커널 파라미터를 제 마음대로 바꾸지 못하게 합니다.

이름 하나로 좁힌 권한

네임스페이스 staging 에서 사용자 ci-deployer 가 Deployment web 하나만 get, patch, update 할 수 있게 Role web-deployer 와 RoleBinding ci-deployer-web 을 만드십시오. 같은 네임스페이스의 다른 Deployment 는 건드릴 수 없어야 하고, Deployment 목록을 볼 수도 없어야 합니다.

규칙에 resourceNames 를 적으면 그 이름의 객체에만 규칙이 적용됩니다. 목록 조회는 이름이 없는 요청이라 resourceNames 로 좁힌 규칙으로는 허용되지 않습니다. Deployment 는 코어 그룹이 아니라 apps 그룹에 있습니다. 주체 종류는 User 이고 apiGroup 은 rbac.authorization.k8s.io 입니다. 확인은 자원 뒤에 이름을 붙여 kubectl auth can-i patch deployments/web 처럼 물어봅니다.

대상과 수명이 정해진 토큰

네임스페이스 staging 에 서비스 계정 agent 를 만들고 파드 collector 를 만드십시오. 파드는 서비스 계정 agent 를 쓰되 기본 토큰 자동 마운트는 끄고, 대신 projected 볼륨 token 으로 대상이 vault 이고 유효 기간이 3600초인 서비스 계정 토큰을 파일 이름 token 으로 발급받아 /var/run/secrets/vault 에 마운트하십시오. 컨테이너 이름은 app 입니다.

projected 볼륨의 sources 에 serviceAccountToken 을 두면 kubelet 이 짧은 수명의 토큰을 발급해 넣습니다. audience 를 적으면 그 대상에게만 쓸 수 있는 토큰이 되고 expirationSeconds 로 수명을 정합니다. 볼륨 안의 파일 이름은 path 로 정합니다. 기본 토큰을 끄는 것은 파드 스펙의 automountServiceAccountToken 이며, 이것을 끄더라도 명시적으로 만든 projected 토큰은 그대로 들어갑니다.

규칙은 한 번, 효력은 한 네임스페이스

ClusterRole namespace-reader 를 만들어 코어 그룹의 pods, services, configmapsget, list, watch 할 수 있게 하십시오. 그리고 사용자 oncall 이 네임스페이스 staging 안에서만 그 권한을 갖도록 RoleBinding oncall-reader 를 만드십시오. 다른 네임스페이스에서는 아무것도 읽을 수 없어야 합니다.

RoleBinding 의 roleRef 는 Role 뿐 아니라 ClusterRole 도 가리킬 수 있고, 그때 규칙의 효력은 그 RoleBinding 이 놓인 네임스페이스 안으로 잘립니다. 같은 ClusterRole 을 ClusterRoleBinding 으로 묶으면 클러스터 전체로 퍼지므로, 다른 네임스페이스에서 no 가 나오는지 확인해야 둘을 구별할 수 있습니다. 주체 종류는 User 이고 apiGroup 은 rbac.authorization.k8s.io 입니다.

컨테이너 수준 seccomp 덮어쓰기

/root/exam/seccomp/net-deny.json 에 seccomp 프로파일을 작성하십시오. 기본 동작은 SCMP_ACT_LOG 이고 socketconnect 시스템 콜은 SCMP_ACT_ERRNO 로 막아야 합니다. 그리고 네임스페이스 staging 에 파드 sensor 를 만들되, 파드 수준에는 RuntimeDefault 프로파일을 두고 컨테이너 app 에서만 이 프로파일을 Localhost 방식으로 profiles/net-deny.json 경로에서 쓰게 하십시오.

seccomp 프로파일은 defaultAction 으로 기본 판정을 정하고 syscalls 배열에서 예외를 적습니다. 기본이 기록(SCMP_ACT_LOG)이면 막을 것만 골라 SCMP_ACT_ERRNO 로 적으면 됩니다. securityContext 는 파드에도 컨테이너에도 있고 컨테이너 쪽이 이깁니다. Localhost 방식의 localhostProfile 은 노드의 seccomp 루트를 기준으로 한 상대 경로입니다.

호스트 계정 권한 최소화

/root/exam/sudoers.d/deploy 에 sudo 규칙을 작성하십시오. 사용자 deploy 가 비밀번호를 묻지 않고 /usr/bin/systemctl restart kubelet 하나만 root 로 실행할 수 있어야 합니다. 명령 자리에 ALL 을 쓴 규칙은 두지 마십시오. 파일은 visudo -cf 의 문법 검사를 통과해야 합니다.

규칙 한 줄의 모양은 '사용자 호스트=(실행계정) 태그: 명령' 입니다. 비밀번호를 묻지 않게 하는 태그는 NOPASSWD: 이고, 명령 자리에 ALL 을 적으면 모든 명령이 열립니다. 명령은 절대 경로로 적고 인자까지 적으면 그 인자로만 제한됩니다. 문법은 visudo -cf 파일이름 으로 확인합니다.

단계적으로 올리는 파드 보안 승인

네임스페이스 payments 를 만들고 파드 보안 승인을 단계적으로 거십시오. enforcebaseline 이고 버전은 v1.31 로 고정합니다. auditwarnrestricted 이고 버전은 latest 입니다. 결과적으로 baseline 을 어기는 파드는 실제로 거부되고, restricted 만 어기는 파드는 경고를 받으면서 만들어져야 합니다.

파드 보안 승인은 네임스페이스 라벨로 켜고, 모드마다 수준을 따로 정할 수 있습니다. enforce 만 막고 audit 과 warn 은 기록과 경고를 남길 뿐입니다. 그래서 앞으로 올릴 수준을 audit 과 warn 에 먼저 걸어 두고 얼마나 걸리는지 본 다음 enforce 를 올리는 것이 실무의 순서입니다. 버전은 같은 접두어에 -version 을 붙인 라벨입니다. 라벨은 여섯 개가 됩니다.

시크릿은 파일로만

네임스페이스 payments 에 시크릿 db-cred 를 만드십시오. 타입은 기본(Opaque)이고 키는 usernamepassword 입니다. 그리고 파드 reporter 를 만들어 이 시크릿을 볼륨 cred/etc/db 에 읽기 전용으로 마운트하되 파일 권한은 8진수 0400 이어야 합니다. 시크릿 값을 환경 변수로는 넣지 마십시오. 컨테이너 이름은 app 입니다.

환경 변수로 넣은 시크릿은 프로세스 목록과 크래시 덤프, 그리고 kubectl describe 에 함께 따라 나옵니다. 파일로 넣으면 그 경로를 읽을 수 있는 프로세스만 봅니다. 볼륨의 파일 권한은 defaultMode 로 정하고 YAML 에서 0 으로 시작하는 수는 8진수로 읽힙니다. 볼륨 마운트에도 readOnly 가 따로 있습니다.

저장 시 암호화 구성

/root/exam/encryption/config.yaml 에 저장 시 암호화 구성을 작성하십시오. apiVersionapiserver.config.k8s.io/v1, kindEncryptionConfiguration 입니다. 암호화 대상은 secrets 이고, 제공자는 aescbc 가 첫 번째이며 identity 가 마지막이어야 합니다. aescbc 의 키는 이름을 갖고 값은 32바이트를 base64 로 적은 것이어야 합니다.

제공자 목록은 순서가 곧 정책입니다. 쓸 때는 첫 번째 제공자를 쓰고 읽을 때는 위에서부터 차례로 시도합니다. 그래서 identity 를 앞에 두면 파일은 멀쩡해 보이는데 시크릿은 평문으로 저장되고, identity 를 아예 빼면 이미 평문으로 저장돼 있던 것을 읽지 못합니다. aescbc 의 키 길이는 정확히 32바이트여야 하며 head -c 32 /dev/urandom | base64 로 만듭니다.

사설 레지스트리 자격 증명

네임스페이스 supply 를 만들고, 레지스트리 registry.internal 에 사용자 deployer 로 접근하는 자격 증명을 시크릿 regcred 로 만드십시오. 서비스 계정 puller 가 그 시크릿으로 이미지를 내려받게 연결하고, Deployment catalog 가 그 서비스 계정을 쓰게 하십시오. 컨테이너 이름은 app 이고 이미지는 registry.internal/catalog:1.4.2 입니다.

kubectl create secret docker-registry 는 --docker-server, --docker-username, --docker-password 를 받아 kubernetes.io/dockerconfigjson 타입의 시크릿을 만듭니다. 일반 시크릿으로 만들면 타입이 Opaque 라 kubelet 이 자격 증명으로 인식하지 못합니다. 서비스 계정에는 imagePullSecrets 필드가 있고, 파드는 serviceAccountName 으로 그 계정을 씁니다. 파드마다 적는 대신 계정에 한 번 붙이면 그 계정을 쓰는 모든 파드에 따라갑니다.

움직이는 태그 차단

네임스페이스 supply 에서 움직이는 태그를 막으십시오. ValidatingAdmissionPolicy no-latest-tag 와 ValidatingAdmissionPolicyBinding no-latest-tag 를 만들고, 파드의 모든 컨테이너와 모든 초기화 컨테이너의 이미지가 :latest 로 끝나지 않을 것을 요구하게 하십시오. 바인딩의 validationActionsDeny 이고 적용 범위는 네임스페이스 supply 뿐입니다. 다른 네임스페이스는 영향을 받으면 안 됩니다.

CEL 의 all() 은 목록의 모든 항목이 조건을 만족하는지 봅니다. 그런데 object.spec.initContainers 는 초기화 컨테이너가 없는 파드에서는 아예 없는 필드라 그대로 참조하면 평가가 실패합니다. has() 로 감싸 없을 때를 함께 다루십시오. 실제로 막으려면 바인딩의 validationActions 에 Deny 가 있어야 하고, Warn 만 두면 경고만 나가고 파드는 만들어집니다. 범위는 바인딩의 matchResources 로 좁힙니다.

이미지 정책 웹훅 구성

/root/exam/imagepolicy/admission-config.yaml 에 승인 구성 파일을 작성하십시오. apiVersionapiserver.config.k8s.io/v1, kindAdmissionConfiguration 이고 플러그인은 ImagePolicyWebhook 하나입니다. 그 설정의 imagePolicykubeConfigFile/etc/kubernetes/imagepolicy/kubeconfig.yaml 을 적고, allowTTL 50, denyTTL 50, retryBackoff 500 을 두며, 웹훅에 닿지 못했을 때 이미지가 허용되지 않도록 defaultAllow 를 거짓으로 두십시오.

defaultAllow 는 웹훅에 닿지 못했을 때의 판정입니다. 참으로 두면 웹훅이 죽는 순간 모든 이미지가 통과하므로 정책의 뜻이 뒤집힙니다. 기본값에 기대지 말고 명시하십시오. 플러그인 설정은 plugins 배열 항목의 configuration 에 인라인으로 적을 수 있고, 그 안의 키 이름은 imagePolicy 입니다.

런타임 탐지 규칙

/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 이 있어야 합니다.

Falco 규칙 파일은 항목들의 목록이고, 항목의 종류는 첫 키로 정해집니다. list 는 이름과 items 를 갖고, rule 은 desc, condition, output, priority, tags 를 갖습니다. 조건 안에서 목록 이름을 괄호로 감싸면 그 목록의 항목 중 하나인지를 묻는 뜻이 됩니다. output 의 %로 시작하는 것은 사건에서 값을 꺼내는 자리이고, 무엇이 어느 파일에 썼는지가 거기에 남아야 나중에 조사가 됩니다.

감사 로그에서 잡음 걷어내기

/root/exam/audit/quiet-policy.yaml 에 감사 정책을 작성하십시오. apiVersionaudit.k8s.io/v1, kindPolicy 이며 규칙은 정확히 네 개이고 순서가 중요합니다. 첫째, 사용자 system:kube-proxywatch 가 코어 그룹의 endpointsservices 에 닿는 것을 None 으로 버립니다. 둘째, 그룹 system:authenticated 의 비자원 경로 /api*/version 접근을 None 으로 버립니다. 셋째, 네임스페이스 payments 의 코어 그룹 secretsRequestResponse 로 남깁니다. 넷째, 대상을 적지 않은 Metadata 규칙으로 나머지 전부를 받습니다.

감사 정책은 위에서부터 훑어 처음 맞는 규칙에서 멈춥니다. 그래서 버릴 것을 앞에 두지 않으면 뒤의 포괄 규칙이 그것까지 전부 기록합니다. 규칙은 자원뿐 아니라 users, userGroups, verbs, namespaces, nonResourceURLs 로도 대상을 좁힐 수 있습니다. level 이 None 이면 그 요청은 기록하지 않습니다. 비자원 경로는 자원과 함께 적지 않고 따로 적습니다.

읽기 전용 루트를 승인 단계에서 강제

네임스페이스 runtime 을 만들고, 그 안에서 만들어지는 파드의 모든 컨테이너가 readOnlyRootFilesystem: true 를 갖도록 강제하십시오. ValidatingAdmissionPolicy immutable-root 와 ValidatingAdmissionPolicyBinding immutable-root 를 만들고, 바인딩의 validationActionsDeny 이며 적용 범위는 네임스페이스 runtime 뿐입니다. 다른 네임스페이스는 영향을 받으면 안 됩니다.

워크로드 하나를 읽기 전용으로 만드는 것과 앞으로 들어올 모든 파드를 그렇게 만드는 것은 다른 일입니다. 뒤엣것은 승인 단계에서 해야 합니다. securityContext 는 없을 수도 있고 그 안의 필드도 없을 수 있으므로, CEL 에서 has() 로 두 단계를 모두 확인하지 않으면 아무것도 적지 않은 파드가 평가 오류로 빠져나가거나 통째로 막힙니다. 적용 범위는 바인딩의 matchResources 로 좁히고, 네임스페이스 하나만 고를 때는 모든 네임스페이스에 자동으로 붙는 kubernetes.io/metadata.name 라벨을 쓰면 됩니다.