Skip to content

Commit

Permalink
docs: add vap generation doc and demo (#3363)
Browse files Browse the repository at this point in the history
Signed-off-by: Rita Zhang <rita.z.zhang@gmail.com>
Co-authored-by: Sertaç Özercan <852750+sozercan@users.noreply.github.com>
  • Loading branch information
ritazh and sozercan committed Apr 25, 2024
1 parent 80d677a commit d2644f7
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 25 deletions.
2 changes: 1 addition & 1 deletion demo/basic/good/good_ns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ kind: Namespace
metadata:
name: good-ns
labels:
"gatekeeper": "true"
"gatekeeper": "true"
2 changes: 1 addition & 1 deletion demo/basic/good/no_dupe_ns.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ kind: Namespace
metadata:
name: no-dupes
labels:
"gatekeeper": "not_duplicated"
"gatekeeper": "not_duplicated"
13 changes: 6 additions & 7 deletions demo/k8s-validating-admission-policy/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
> [!WARNING]
> This is a demo of a prototype-stage feature and is subject to change.
> This is a demo of an alpha feature and is subject to change.
This demo shows two new capabilities:
1. Together with Gatekeeper and gator CLI, you can get admission, audit, and shift left validations for both CEL-based Validating Admission Policy and OPA Rego policies, even for clusters that do not support Kubernetes Validating Admission Policy feature yet.
1. Gatekeeper can be enabled to generate Kubernetes Validating Admission Policy resources such that admission validation can be handled by [Kubernetes's in-process Validating Admission Policy Controller](https://kubernetes.io/docs/reference/access-authn-authz/validating-admission-policy/) instead of the Gatekeeper admission webhook. In the event the Validating Admission Policy Controller fails open, then Gatekeeper admission webhook can act as a fallback. This requires clusters with the Kubernetes Validating Admission Policy feature enabled.

## Pre-requisites

- Requires minimum Gatekeeper v3.14.0
- Set `--experimental-enable-k8s-native-validation` in Gatekeeper deployments.
- Set `--validate-template-rego=false` in Gatekeeper deployments if using Gatekeeper version 3.14.0 and later. This flag will be removed in v3.16.0, and will not be applicable in the future.
Please refer to https://open-policy-agent.github.io/gatekeeper/website/docs/next/validating-admission-policy for pre-requisites and configuration steps.

## Demo

<img width= "900" height="500" src="demo.gif" alt="cel demo">
<img width= "900" height="500" src="demo.gif" alt="vap demo">
4 changes: 0 additions & 4 deletions demo/k8s-validating-admission-policy/bad_namespace.yaml

This file was deleted.

Binary file modified demo/k8s-validating-admission-policy/demo.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 49 additions & 0 deletions demo/k8s-validating-admission-policy/demo.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/bin/bash

. ../../third_party/demo-magic/demo-magic.sh

clear

p "To ensure the ValidatingAdmissionPolicy feature is enabled for the cluster"

pe "kubectl api-resources | grep ValidatingAdmissionPolicy"

p "Deploy the constraint template"

pe "kubectl apply -f k8srequiredlabels_template.yaml"

p "View Constraint template to see a new engine and CEL rules are added"

pe "cat k8srequiredlabels_template.yaml"

pe "kubectl apply -f owner_must_be_provided.yaml"

pe "cat owner_must_be_provided.yaml"

p "Let's test the policy"

pe "kubectl create ns test"

p "Note the bad namespace was blocked by the Gatekeeper webhook as evaluated by the new CEL rules"

p "Now let's update the constraint template to generate the ValidatingAdmissionPolicy resources"

pe "kubectl apply -f k8srequiredlabels_template_usevap.yaml"

pe "cat k8srequiredlabels_template_usevap.yaml"

p "Notice the "gatekeeper.sh/use-vap": "yes" label was added to the template to generate ValidatingAdmissionPolicy resources. Let's see what the generated resources look like"

pe "kubectl get ValidatingAdmissionPolicy"

pe "kubectl get ValidatingAdmissionPolicyBinding"

p "Let's test the policy"

pe "kubectl create ns test"

p "Note the bad namespace was blocked by the ValidatingAdmissionPolicy admission controller"

p "THE END"

kubectl delete constrainttemplates --all
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
labels:
"gatekeeper.sh/use-vap": "yes"
spec:
crd:
spec:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
name: k8srequiredlabels
labels:
"gatekeeper.sh/use-vap": "yes"
spec:
crd:
spec:
names:
kind: K8sRequiredLabels
validation:
# Schema for the `parameters` field
openAPIV3Schema:
type: object
properties:
message:
type: string
labels:
type: array
items:
type: object
properties:
key:
type: string
allowedRegex:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
code:
- engine: K8sNativeValidation
source:
validations:
- expression: '[object, oldObject].exists(obj, obj != null && has(obj.metadata) && variables.params.labels.all(entry, has(obj.metadata.labels) && entry.key in obj.metadata.labels))'
messageExpression: '"missing required label, requires all of: " + variables.params.labels.map(entry, entry.key).join(", ")'
- expression: '[object, oldObject].exists(obj, obj != null && !variables.params.labels.exists(entry, has(obj.metadata.labels) && entry.key in obj.metadata.labels && !string(obj.metadata.labels[entry.key]).matches(string(entry.allowedRegex))))'
message: "regex mismatch"
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
name: all-must-have-owner
labels:
"gatekeeper.sh/use-vap": "yes"
spec:
match:
kinds:
Expand Down
80 changes: 72 additions & 8 deletions website/docs/validating-admission-policy.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ id: validating-admission-policy
title: Integration with Kubernetes Validating Admission Policy
---

`Feature State`: Gatekeeper version v3.13+ (pre-alpha)
`Feature State`: Gatekeeper version v3.16 (alpha)

> ❗ This feature is pre-alpha, subject to change (feedback is welcome!). It is disabled by default. To enable the feature,
> set the `experimental-enable-k8s-native-validation` flag to true and use the [development build of Gatekeeper](https://open-policy-agent.github.io/gatekeeper/website/docs/install/#deploying-a-release-using-development-image).
> ❗ This feature is alpha, subject to change (feedback is welcome!). It is disabled by default.
## Description

This feature allows Gatekeeper to integrate with Kubernetes Validating Admission Policy based on [Common Expression Language (CEL)](https://github.com/google/cel-spec), a declarative, in-process admission control alternative to validating admission webhooks.

## Motivations

The Validating Admission Policy feature (disabled by default) was introduced as an alpha feature to Kubernetes v1.26, beta in v1.28. Some of the benefits include:
The Validating Admission Policy feature was introduced as an alpha feature to Kubernetes v1.26, beta in v1.28 (disabled by default), GA in v1.30 (enabled by default). Some of the benefits include:
- in-tree/native in-process
- reduce admission request latency
- improve reliability and availability
Expand All @@ -25,9 +24,51 @@ To reduce policy fragmentation and simplify the user experience by standardizing

The [Constraint Framework](https://github.com/open-policy-agent/frameworks/tree/master/constraint) is the library that underlies Gatekeeper. It provides the execution flow Gatekeeper uses to render a decision to the API server. It also provides abstractions that allow us to define constraint templates and constraints: Engine, Enforcement Points, and Targets.

Together with Gatekeeper and [gator CLI](gator.md), you can get admission, audit, and shift left validations for both CEL-based Validating Admission Policy and OPA Rego policies, even for clusters that do not support Validating Admission Policy feature yet.
Together with Gatekeeper and [gator CLI](gator.md), you can get admission, audit, and shift left validations for policies written in both CEL and Rego policy languages, even for clusters that do not support Validating Admission Policy feature yet. For simple policies, you may want admission requests to be handled by the K8s built-in Validating Admission Controller (only supports CEL) instead of the Gatekeeper admission webhook.

## Example Constraint Template
To summary, these are potential options when running Gatekeeper:

| Policy Language(s) | Enforcement Point |
| ------------------ | ------------------ |
| CEL, Rego | Gatekeeper validating webhook |
| CEL, Rego | Gatekeeper Audit |
| CEL, Rego | Gator CLI |
| CEL | K8s built-in Validating Admission Controller (aka ValidatingAdmissionPolicy) |
| Rego | Gatekeeper validating webhook (referential policies, external data) |
| Rego | Gatekeeper Audit (referential policies, external data) |
| Rego | Gator CLI (referential policies) |

## Pre-requisites

- Requires minimum Gatekeeper v3.16.0
- Requires minimum Kubernetes v1.30, when the `Validating Admission Policy` feature GAed
- [optional] Kubernetes version v1.29, need to enable feature gate and runtime config as shown below:

```yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
ValidatingAdmissionPolicy: true
runtimeConfig:
admissionregistration.k8s.io/v1beta1: true
```
- Set `--experimental-enable-k8s-native-validation` in Gatekeeper deployments, or `enableK8sNativeValidation=true` if using Helm.

## Get started

### Option 1: Install with Helm
Update the `enableK8sNativeValidation` parameter in values.yaml or set during deployment
- Enable the K8s Native Validating driver to allow users to create CEL-based rules in addition to the OPA driver and rego rules (alpha feature). Default is `false`
```shell
helm install gatekeeper/gatekeeper --name-template=gatekeeper --namespace gatekeeper-system --create-namespace \
--set enableK8sNativeValidation=true
```

### Option 2: Install with Gatekeeper deployment
Edit the applicable deployments (`controller-manager` and `audit`), and update the following commandline flags:
- Set `--experimental-enable-k8s-native-validation=true`

## Policy updates to add CEL
To see how it works, check out this [demo](https://github.com/open-policy-agent/gatekeeper/tree/master/demo/k8s-validating-admission-policy)

Example `K8sRequiredLabels` constraint template using the `K8sNativeValidation` engine and CEL expressions that requires resources to contain specified labels with values matching provided regular expressions. A similar policy written in Rego can be seen [here](https://open-policy-agent.github.io/gatekeeper-library/website/validation/requiredlabels)
Expand Down Expand Up @@ -64,8 +105,31 @@ spec:
- engine: K8sNativeValidation
source:
validations:
- expression: "variables.params.labels.all(entry, has(object.metadata.labels) && entry.key in object.metadata.labels)"
- expression: '[object, oldObject].exists(obj, obj != null && has(obj.metadata) && variables.params.labels.all(entry, has(obj.metadata.labels) && entry.key in obj.metadata.labels))'
messageExpression: '"missing required label, requires all of: " + variables.params.labels.map(entry, entry.key).join(", ")'
- expression: "!variables.params.labels.exists(entry, has(object.metadata.labels) && entry.key in object.metadata.labels && !string(object.metadata.labels[entry.key]).matches(string(entry.allowedRegex)))"
- expression: '[object, oldObject].exists(obj, obj != null && !variables.params.labels.exists(entry, has(obj.metadata.labels) && entry.key in obj.metadata.labels && !string(obj.metadata.labels[entry.key]).matches(string(entry.allowedRegex))))'
message: "regex mismatch"
rego: |
...
```
With this new engine and source added to the constraint template, now Gatekeeper webhook, audit, and shift-left can validate resources with these new CEL-based rules.

## Policy updates to generate Validating Admission Policy resources

For some policies, you may want admission requests to be handled by the K8s Validating Admission Controller instead of the Gatekeeper admission webhook. By default, Gatekeeper is configured to generate K8s Validating Admission Policy resources if the `gatekeeper.sh/use-vap` label is used. In the event K8s Validating Admission Controller fails open, then Gatekeeper admission webhook can act as a backup. Default value for this feature flag is `--vap-enforcement=GATEKEEPER_DEFAULT`.

Other allowed values are:
- `NONE`: do not generate
- `GATEKEEPER_DEFAULT`: do not generate unless label `gatekeeper.sh/use-vap: yes` is added to policy explicitly
- `VAP_DEFAULT`: generate unless label `gatekeeper.sh/use-vap: no` is added to policy explicitly

To explicitly enable Gatekeeper to generate K8s Validating Admission Policy resources at the constraint template level, add the following label to the constraint template resource:
```yaml
labels:
"gatekeeper.sh/use-vap": "yes"
```
By default, constraints will inherit the same behavior as the constraint template. However this behavior can be overriden by adding the following label to the constraint resource:
```yaml
labels:
"gatekeeper.sh/use-vap": "no"
```

0 comments on commit d2644f7

Please sign in to comment.