ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • OPA Gatekeeper - Constraint, ConstraintTemplate
    DevOps/DevSecOps 2020. 9. 4. 16:17

    앞선 포스팅에서 OPA 와 Gatekeeper 의 개념에 대해서 살펴보았다. 그럼 Gatekeeper 에서 사용하는 Constraint와 ContraintTemplate을 조금 더 자세히 알아보려고 한다.

    개념

    1. Constraint: 한 시스템이 만족시켜야 하는 요구사항 세트.
    2. Enforcement Point: Contraint 가 강제되는 곳. Git hooks 이나 Kubernetes admission controllers, audit systems 이 그 예시. contraint 기반의 정책이 여러 곳에 공통으로 적용되도록.
    3. ContraintTemplate: Contraint를 정의하도록 해줌. expected input parameter 와 Rego 정책을 담음.

    다시 풀어서 말하면, OPA에서 사용하는 Rego 정책을 K8S가 읽을 수 있는 형태의 CustomResource (CRD)로 한 번 더 감싼 뒤 필요한 K8S 관련 인풋을 정의하게 해주는 게 ConstraintTemplate. 여기에서 정의한 CRD 의 구현체이자, 이 정책의 적용 대상이 되는 애들을 지정하고 허용/불용 정책을 지정하는 것이 Constraint 이다.

    아래는 예시를 통해 Rego 정책이 어떻게 ConstraintTemplate 에 포함되어, 실제 정책인 Constraint 가 정의되는지 살펴본다. 아래 정책은 katakota의 튜토리얼 정책을 그대로 가지고 왔음을 밝힌다.

     

    ConstraintTemplate과 Constraint의 관계

    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
Designed by Tistory.