-
OPA Gatekeeper - Constraint, ConstraintTemplateDevOps/DevSecOps 2020. 9. 4. 16:17
앞선 포스팅에서 OPA 와 Gatekeeper 의 개념에 대해서 살펴보았다. 그럼 Gatekeeper 에서 사용하는 Constraint와 ContraintTemplate을 조금 더 자세히 알아보려고 한다.
개념
- Constraint: 한 시스템이 만족시켜야 하는 요구사항 세트.
- Enforcement Point: Contraint 가 강제되는 곳. Git hooks 이나 Kubernetes admission controllers, audit systems 이 그 예시. contraint 기반의 정책이 여러 곳에 공통으로 적용되도록.
- ContraintTemplate: Contraint를 정의하도록 해줌. expected input parameter 와 Rego 정책을 담음.
다시 풀어서 말하면, OPA에서 사용하는 Rego 정책을 K8S가 읽을 수 있는 형태의 CustomResource (CRD)로 한 번 더 감싼 뒤 필요한 K8S 관련 인풋을 정의하게 해주는 게 ConstraintTemplate. 여기에서 정의한 CRD 의 구현체이자, 이 정책의 적용 대상이 되는 애들을 지정하고 허용/불용 정책을 지정하는 것이 Constraint 이다.
아래는 예시를 통해 Rego 정책이 어떻게 ConstraintTemplate 에 포함되어, 실제 정책인 Constraint 가 정의되는지 살펴본다. 아래 정책은 katakota의 튜토리얼 정책을 그대로 가지고 왔음을 밝힌다.
ConstraintTemplate의 필드 구조
* validation: Constraint의 parameters 필드 스키마
* target: Contraint가 적용될 대상.
* rego: 정책
* libs: rego 패키지가 사용하는 헬퍼 정의. libs에 있는 모든 패키지들은 lib prefix 붙여서 불러야 함. package lib.<sth>예시로 보는 ConstraintTemplate, Constraint 의 관계 - 레지스트리 제한
ConstraintTemplate
apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: whitelistedregistry spec: crd: spec: names: kind: WhitelistedRegistry listKind: WhitelistedRegistryList plural: whitelistedregistries singular: whitelistedregistry validation: # Schema for the `parameters` field in the constraint openAPIV3Schema: properties: registries: type: array items: string targets: - target: admission.k8s.gatekeeper.sh rego: | package whitelistedregistires whitelisted_registries = {registry | registry = input.parameters.registries[_] } registry_whitelisted(str, patterns) { registry_matches(str, patterns[_]) } registry_matches(str, pattern) { contains(str, pattern) } violation[{"msg": msg}] { input.review.object image := input.review.object.spec.containers[_].image name := input.review.object.metadata.name not registry_whitelisted(image, whitelisted_registries) msg := sprintf("pod %q has invalid registry %q. Registry should be one of %v", [name, image, whitelisted_registries]) }
Constraint
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: WhitelistedRegistry metadata: name: whitelisted-registry spec: match: kinds: - apiGroups: [""] kinds: ["Pod"] parameters: registries: - quay.io - k8s.gcr.io - atheiman
apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: requiredlabels spec: crd: spec: names: kind: RequiredLabels listKind: RequiredLabelsList plural: requiredlabels singular: requiredlabels validation: # Schema for the `parameters` field in the constraint openAPIV3Schema: properties: labels: type: array items: string targets: - target: admission.k8s.gatekeeper.sh rego: | package requiredlabels violation[{"msg": msg, "details": {"missing_labels": missing}}] { provided := {label | input.review.object.metadata.labels[label]} required := {label | label := input.parameters.labels[_]} missing := required - provided count(missing) > 0 msg := sprintf("you must provide labels for object %v : %v", [input.review.object.kind ,missing]) }
예시로 보는 ConstraintTemplate, Constraint 의 관계 - Label
ConstraintTemplate
apiVersion: templates.gatekeeper.sh/v1beta1 kind: ConstraintTemplate metadata: name: requiredlabels spec: crd: spec: names: kind: RequiredLabels listKind: RequiredLabelsList plural: requiredlabels singular: requiredlabels validation: # Schema for the `parameters` field in the constraint openAPIV3Schema: properties: labels: type: array items: string targets: - target: admission.k8s.gatekeeper.sh rego: | package requiredlabels violation[{"msg": msg, "details": {"missing_labels": missing}}] { provided := {label | input.review.object.metadata.labels[label]} required := {label | label := input.parameters.labels[_]} missing := required - provided count(missing) > 0 msg := sprintf("you must provide labels for object %v : %v", [input.review.object.kind ,missing]) }
Constraint
apiVersion: constraints.gatekeeper.sh/v1beta1 kind: RequiredLabels metadata: name: resources-must-have-owner spec: match: namespace: ["default"] kinds: - apiGroups: [""] kinds: ["Pod"] - apiGroups: ["apps"] kinds: ["Deployment"] parameters: labels: - owner
'DevOps > DevSecOps' 카테고리의 다른 글
어플리케이션 라이프사이클에 따른 OPA 정책 적용 (0) 2020.09.06 OPA 와 OPA Gatekeeper (1) 2020.08.07 컨테이너 이미지 스캔 베스트 프랙티스 (0) 2020.07.26