LabHub

CKS — 쿠버네티스 보안 전문가 · 공급망 보안 · 실습

CEL 로 쓰는 어드미션 정책

LabHub 에서 이어서 보기

목표

외부 웹훅 서버 없이 API 서버 안에서 CEL 로 동작하는 ValidatingAdmissionPolicy 를 직접 만들고,
바인딩으로 적용 범위를 좁힌 뒤, 전통적인 ValidatingWebhookConfiguration 오브젝트도 함께
작성해 두 방식의 차이를 손으로 확인합니다.

왜 중요한가

RBAC 은 "Pod 를 만들 수 있는가"까지만 답합니다. 그 Pod 가 privileged 인지, 허용된 레지스트리의
이미지인지는 RBAC 으로 표현할 수 없습니다. 이 간극을 메우는 것이 어드미션 정책입니다.

전통적인 방법은 ValidatingWebhookConfiguration 으로 외부 서버를 등록하는 것인데, 여기에는
가용성 함정이 있습니다. failurePolicy: Fail 로 등록된 웹훅의 서버가 죽으면 대상 리소스의
생성이 전부 거부되어 배포가 통째로 멈춥니다. 정책을 지키려다 클러스터를 세우는 것입니다.
ValidatingAdmissionPolicy 는 API 서버 안에서 CEL 표현식을 평가하므로 네트워크 홉과 외부
프로세스가 사라지고, 이 실패 모드 자체가 줄어듭니다.

정책과 바인딩이 분리된 것도 의도된 설계입니다. 정책은 "무엇이 위반인가"만 정의하고, 바인딩이
"어디에, 얼마나 세게 적용할 것인가"를 정합니다. 같은 정책을 스테이징에서는 Warn 으로,
프로덕션에서는 Deny 로 켤 수 있습니다.

단계

1. 네임스페이스 cks-admission 을 만들고 라벨 cks-policy=enforce 를 붙인다.
2. ValidatingAdmissionPolicy cks-no-latest-tag 를 만든다.
spec.matchConstraints.resourceRules[0] 은 apiGroups apps, apiVersions v1,
operations CREATEUPDATE, resources deployments 다.
(API 서버는 validationsauditAnnotations 도 없는 정책을 거부한다. 이 단계에서는
expression: "true" 같은 자리표시자 검증식을 하나 넣어 두고, 3 단계에서 진짜 표현식으로
바꾼다.)
3. 같은 정책에 spec.validations[0] 을 넣는다. expression 은 Deployment 의 모든 컨테이너
이미지가 :latest 로 끝나지 않는지 검사하는 CEL 이고(object.spec.template.spec.containers
all 이 들어가야 한다), message 는 비어 있으면 안 된다.
4. 같은 정책의 spec.failurePolicyFail 로 설정한다.
5. ValidatingAdmissionPolicyBinding cks-no-latest-tag-binding 을 만든다. policyName
cks-no-latest-tag, validationActionsDeny,
matchResources.namespaceSelector.matchLabelscks-policy: enforce 다.
6. ValidatingAdmissionPolicy cks-no-privileged 를 만든다. matchConstraints 는 코어 그룹
(apiGroups 는 빈 문자열), apiVersions v1, operations CREATE·UPDATE, resources pods
이고, validations[0].expression 에는 privileged 라는 단어와 object.spec.containers
들어가야 하며 message 도 있어야 한다.
7. ValidatingWebhookConfiguration cks-image-verify 를 만든다. 웹훅 하나(name
verify.images.cks.local)를 두고 failurePolicyIgnore, sideEffectsNone,
admissionReviewVersionsv1, clientConfig.service 는 네임스페이스 cks-admission
의 서비스 image-verifier, rules 는 코어 그룹 v1pods 에 대한 CREATE 다.
8. cks-admission 에 Deployment checkout 을 만든다. replicas 2, 셀렉터와 파드 라벨은
app=checkout, 파드 템플릿에 라벨 app.kubernetes.io/name=checkout 도 넣는다.
컨테이너 이름은 app, 이미지는 @sha256: 로 고정하고 :latest 를 쓰지 않으며,
컨테이너 securityContext 에 privileged: falseallowPrivilegeEscalation: false
명시한다.

참고

단계 8개

  1. 정책을 적용할 네임스페이스
  2. ValidatingAdmissionPolicy 골격
  3. CEL 표현식으로 검증 규칙 쓰기
  4. failurePolicy 정하기
  5. 바인딩으로 정책 켜기
  6. privileged 금지 정책 추가
  7. ValidatingWebhookConfiguration 작성
  8. 종합: 정책을 통과하는 배포