liveBook · Manning

ConstraintTemplate

As explained in Google Anthos in Action

A constraint template library is a collection of reusable Gatekeeper templates that define policy constraints and their validation logic.

A ConstraintTemplate library is a reusable collection of Gatekeeper policy definitions. Each ConstraintTemplate supplies evaluation logic; a separate constraint selects a template and provides the scope and parameters that make its policy effective. In Policy Controller, templates are available when Gatekeeper is enabled, but a template alone does not enforce a rule. section 11.2.3 section 13.4.1

The default Policy Controller library included 32 templates at the time described, covering cases such as allowed container registries, resource constraints, and privileged containers. Inspect the templates installed on a cluster with `kubectl get constrainttemplates`. Custom templates can extend the library when the supplied definitions do not fit a requirement. section 13.4.1 section 11.2.3

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
 name: k8simagedigests
 annotations:
   metadata.gatekeeper.sh/title: "Image Digests"
   description: >-
     Requires container images to contain a digest.

     https://kubernetes.io/docs/concepts/containers/images/
spec:
 crd:
   spec:
     names:
       kind: K8sImageDigests
     validation:
       openAPIV3Schema:
         type: object
         description: >-
           Requires container images to contain a digest.

           https://kubernetes.io/docs/concepts/containers/images/
         properties:
           exemptImages:
             description: >-
               Any container that uses an image that matches an entry in this list will be excluded
               from enforcement. Prefix-matching can be signified with '*'. For example: 'my-image-*'.

               It is recommended that users use the fully-qualified Docker image name (e.g. start with a domain name)
               in order to avoid unexpectedly exempting images from an untrusted repository.
             type: array
             items:
               type: string
 targets:
   - target: admission.k8s.gatekeeper.sh
     rego: |
       package k8simagedigests

       import data.lib.exempt_container.is_exempt

       violation[{"msg": msg}] {
         container := input.review.object.spec.containers[_]
         not is_exempt(container)
         satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)]
         not all(satisfied)
         msg := sprintf("container <%v> uses an image without a digest <%v>", [container.name, container.image])
       }

       violation[{"msg": msg}] {
         container := input.review.object.spec.initContainers[_]
         not is_exempt(container)
         satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)]
         not all(satisfied)
         msg := sprintf("initContainer <%v> uses an image without a digest <%v>", [container.name, container.image])
       }

       violation[{"msg": msg}] {
         container := input.review.object.spec.ephemeralContainers[_]
         not is_exempt(container)
         satisfied := [re_match("@[a-z0-9]+([+._-][a-z0-9]+)*:[a-zA-Z0-9=_-]+", container.image)]
         not all(satisfied)
         msg := sprintf("ephemeralContainer <%v> uses an image without a digest <%v>", [container.name, container.image])
       }
     libs:
       - |
         package lib.exempt_container

         is_exempt(container) {
             exempt_images := object.get(object.get(input, "parameters", {}), "exemptImages", [])
             img := container.image
             exemption := exempt_images[_]
             _matches_exemption(img, exemption)
         }

         _matches_exemption(img, exemption) {
             not endswith(exemption, "*")
             exemption == img
         }

         _matches_exemption(img, exemption) {
             endswith(exemption, "*")
             prefix := trim_suffix(exemption, "*")
             startswith(img, prefix)
         }

This `ConstraintTemplate` manifest illustrates the reusable-definition side: it names a `K8sImageDigests` constraint kind and declares a validation schema for parameters such as exempt images. A separate constraint is needed to apply it. section 13.4.1

Allow only trusted image registries

Create a `K8sAllowedRepos` constraint named `allowed-registries`, match Pods, and set `parameters.repos` to `gcr.io` and `hub.evermore.local`. A Pod using `bitnami/nginx` is then denied by the admission webhook as an invalid image repository. The reusable template defines the check; the constraint supplies this cluster’s allowed registries. section 13.9.1 section 11.2.3

Test disruptive constraints before enforcing them. A privileged-container constraint can use `enforcementAction: dryrun` to report violations, while `excludedNamespaces` keeps specified system namespaces outside its scope. Review the reported Pods before switching to enforcement; otherwise, a security policy may block workloads the cluster needs. section 13.4.1 section 13.9.1

How Google Anthos in Action covers it

How deep it goes
Explains the template–constraint division, inspection command, and example manifests, but does not work through writing Rego logic.
Examples
Uses image-digest and allowed-registry policies, plus dry-run privileged-container violations and namespace exclusions.
What it assumes
Assumes familiarity with Kubernetes Pods, namespaces, and YAML manifests while explaining the distinct roles of templates and constraints.
What you can do after
Apply it via Gatekeeper constraints to configure existing templates, inspect available definitions, and test policy effects before enforcement.
How it connects
Connects ConstraintTemplates to Rego, Gatekeeper constraints, Policy Controller, admission control, and ClusterSelectors.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Google Anthos in Action. The section links point to the parts of the book it draws on.