監査ポリシーを設計する
한국어 원문으로 표시합니다.
목표
audit.k8s.io/v1 감사 정책 파일을 규칙 하나씩 쌓아 만들면서, 규칙 순서와 레벨 선택이
무엇을 남기고 무엇을 버리는지 직접 확인합니다.
왜 중요한가
침해 대응의 첫 질문은 언제나 "언제, 누가, 무엇을 했는가"이고, 쿠버네티스에서 그것에 답할 수 있는 유일한 자료가 API 서버 감사 로그입니다. 전부 기록하면 비용이 폭발하고, 대충 기록하면 정작 필요할 때 아무것도 없습니다. 그래서 감사 정책은 "무엇을 기록할까"가 아니라 "무엇을 버릴까"를 정하는 문서입니다.
가장 흔한 실수 두 가지를 이 실습에서 직접 겪습니다. 첫째, 규칙은 위에서부터 평가되어 처음
매칭된 하나만 적용되므로 제외 규칙(level: None)이 아래에 있으면 아무 효과가 없습니다.
둘째, Secret 에 RequestResponse 를 걸면 감사 로그 파일 안에 시크릿 값이 그대로 들어갑니다.
감사 로그 수집 시스템은 대개 애플리케이션보다 접근 권한이 넓으므로, 지키려던 것을 퍼뜨리는
결과가 됩니다.
이 환경에서는 감사 로그를 실제로 켤 수 없습니다(kwok 컨트롤 플레인에는 정책 파일을 다시 물릴
수 없습니다). 채점은 정책 파일의 내용과 순서만 봅니다. CKS 시험에서 채점하는 것도 결국 이
파일입니다. Falco 규칙과 crictl 로 하는 런타임 조사는 이 모듈의 읽기와 퀴즈에서 다룹니다.
단계
/root/cks-audit-runtime/audit-policy.yaml을 만든다.apiVersion: audit.k8s.io/v1,kind: Policy이고,rules의 맨 마지막 규칙은 아무 조건 없이level: Metadata인 포괄 규칙이다.- 같은 파일의 최상위에
omitStages를 두고RequestReceived를 넣는다. rules에 Secret 과 ConfigMap 을level: Metadata로 기록하는 규칙을 추가한다. 코어 그룹의secrets와configmaps를 대상으로 한다. 파일 안 어떤 규칙도secrets에 대해Request나RequestResponse를 지정하면 안 된다.rules의 가장 위에 kube-system 네임스페이스의secretsget요청을level: None으로 제외하는 규칙을 넣는다. 이 규칙의 위치는 3 단계에서 만든 규칙보다 반드시 앞이어야 한다.rules에 RBAC 리소스(rbac.authorization.k8s.io그룹의roles,rolebindings,clusterroles,clusterrolebindings)에 대한escalate,bind,impersonate동사를level: RequestResponse로 기록하는 규칙을 추가한다.rules에 코어 그룹pods의create,update,patch,delete를level: Request로 기록하는 규칙을 추가한다./root/cks-audit-runtime/apiserver-audit-flags.txt에 API 서버에 붙일 플래그를 한 줄에 하나씩 쓴다.--audit-policy-file=/etc/kubernetes/audit-policy.yaml,--audit-log-path=/var/log/kubernetes/audit.log,--audit-log-maxage=30,--audit-log-maxbackup=10,--audit-log-maxsize=100다섯 개다.
참고
- 규칙 하나의 모양:
- level: None아래에resources,namespaces,verbs를 필요한 만큼 붙입니다. resources항목은- group: ""과resources: [...]쌍의 목록입니다. 코어 그룹은 빈 문자열입니다.yq '.rules | length' /root/cks-audit-runtime/audit-policy.yaml로 규칙 개수를 확인하면 순서를 점검하기 쉽습니다.- 흔한 실수 1:
level: None제외 규칙을 파일 아래쪽에 둡니다. 위쪽 규칙이 먼저 매칭되어 아무 효과가 없습니다. - 흔한 실수 2: 포괄 규칙을 맨 위에 둡니다. 그러면 아래 규칙들이 절대 평가되지 않습니다.
감사 정책 골격과 포괄 규칙
/root/cks-audit-runtime/audit-policy.yaml 을 만든다. apiVersion: audit.k8s.io/v1,
kind: Policy 이고, rules 의 맨 마지막 규칙은 아무 조건 없이 level: Metadata 인
포괄 규칙이다.
정책은 audit.k8s.io/v1 의 Policy 리소스입니다. 아무것도 매칭되지 않은 요청을 받아 줄 포괄 규칙이 맨 아래에 있어야 합니다.
잡음 단계 제거
같은 파일의 최상위에 omitStages 를 두고 RequestReceived 를 넣는다.
하나의 요청은 여러 단계에서 이벤트를 만듭니다. 요청을 받은 시점의 이벤트는 대부분 쓸모가 없습니다. 최상위 필드로 지정하면 전체에 적용됩니다.
Secret 은 메타데이터까지만
rules 에 Secret 과 ConfigMap 을 level: Metadata 로 기록하는 규칙을 추가한다.
코어 그룹의 secrets 와 configmaps 를 대상으로 한다. 파일 안 어떤 규칙도 secrets 에
대해 Request 나 RequestResponse 를 지정하면 안 된다.
Secret 에 Request 이상 레벨을 걸면 감사 로그 파일 안에 시크릿 값이 그대로 들어갑니다. 어떤 규칙도 secrets 에 대해 Request 이상을 지정하면 안 됩니다.
kube-system 잡음 제외
rules 의 가장 위에 kube-system 네임스페이스의 secrets get 요청을
level: None 으로 제외하는 규칙을 넣는다. 이 규칙의 위치는 3 단계에서 만든 규칙보다
반드시 앞이어야 한다.
규칙은 위에서부터 평가되어 처음 매칭된 하나만 적용됩니다. 제외 규칙이 아래에 있으면 위쪽 규칙이 먼저 잡아 버립니다.
권한 상승 시도는 전부 기록
rules 에 RBAC 리소스(rbac.authorization.k8s.io 그룹의 roles, rolebindings,
clusterroles, clusterrolebindings)에 대한 escalate, bind, impersonate 동사를
level: RequestResponse 로 기록하는 규칙을 추가한다.
RBAC 리소스는 코어 그룹이 아니라 rbac.authorization.k8s.io 그룹입니다. verbs 에 위험 동사 세 개를 모두 적으세요.
파드 변경은 요청 본문까지
rules 에 코어 그룹 pods 의 create, update, patch, delete 를
level: Request 로 기록하는 규칙을 추가한다.
조회는 빼고 변경 동사만 고릅니다. 요청 본문을 남기면 침해 후 어떤 매니페스트가 배포됐는지 재구성할 수 있습니다.
종합: 감사 로그 백엔드 플래그 문서화
/root/cks-audit-runtime/apiserver-audit-flags.txt 에 API 서버에 붙일 플래그를 한 줄에
하나씩 쓴다. --audit-policy-file=/etc/kubernetes/audit-policy.yaml,
--audit-log-path=/var/log/kubernetes/audit.log, --audit-log-maxage=30,
--audit-log-maxbackup=10, --audit-log-maxsize=100 다섯 개다.
정책 파일 위치, 로그 출력 위치, 그리고 회전 정책 세 가지를 모두 적어야 합니다. 회전 설정이 없으면 디스크가 차고, 디스크가 차면 API 서버가 멈춥니다.