-
Notifications
You must be signed in to change notification settings - Fork 757
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Signed-off-by: Jaydip Gabani <[email protected]> Co-authored-by: Sertaç Özercan <[email protected]>
- Loading branch information
1 parent
8e2aea5
commit b363b40
Showing
7 changed files
with
333 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
This is a demo of a prototype-stage feature and is subject to change. | ||
|
||
The demo will not work unless the --experimental-enable-k8s-native-validation is | ||
set. | ||
The demo will not work unless the `--experimental-enable-k8s-native-validation`` is | ||
set. Please set `--validate-template-rego` to `false` if using Gatekeeper version 3.13.1+ but before 3.16.0. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
--- | ||
id: validating-admission-policy | ||
title: Integration with Kubernetes Validating Admission Policy | ||
--- | ||
|
||
`Feature State`: Gatekeeper version v3.13+ (pre-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). Do not use this feature with `validate-template-rego` flag enabled, as the policies with CEL would get rejected with Rego compilation error. | ||
## 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: | ||
- in-tree/native in-process | ||
- reduce admission request latency | ||
- improve reliability and availability | ||
- able to fail closed without impacting availability | ||
- avoid the operational burden of webhooks | ||
|
||
To reduce policy fragmentation and simplify the user experience by standardizing the policy experience. We have created an abstraction layer that provides multi-language (e.g. Rego and CEL), multi-target policy enforcement to allow for portable policies and coexistence of numerous policy implementations. | ||
|
||
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. | ||
|
||
## Example Constraint Template | ||
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) | ||
|
||
```yaml | ||
apiVersion: templates.gatekeeper.sh/v1 | ||
kind: ConstraintTemplate | ||
metadata: | ||
name: k8srequiredlabels | ||
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: "variables.params.labels.all(entry, has(object.metadata.labels) && entry.key in object.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)))" | ||
message: "regex mismatch" | ||
``` |
161 changes: 161 additions & 0 deletions
161
website/versioned_docs/version-v3.13.x/constrainttemplates.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
--- | ||
id: constrainttemplates | ||
title: Constraint Templates | ||
--- | ||
|
||
ConstraintTemplates define a way to validate some set of Kubernetes objects in Gatekeeper's Kubernetes [admission controller](https://kubernetes.io/blog/2019/03/21/a-guide-to-kubernetes-admission-controllers/). They are made of two main elements: | ||
|
||
1. [Rego](https://www.openpolicyagent.org/docs/latest/#rego) code that defines a policy violation | ||
2. The schema of the accompanying `Constraint` object, which represents an instantiation of a `ConstraintTemplate` | ||
|
||
> ❗ Validation of Rego for constraint templates is enabled by default. Set `validate-template-rego` flag to `false` to disable rego validation if you want to use `experimental-enable-k8s-native-validation` Kubernetes CEL based policies as well. This flag will be removed from Gatekeeper 3.16 and later, please make use of [Gator](https://open-policy-agent.github.io/gatekeeper/website/docs/gator) to validate constraint template in shift left manner to avoid any impact with this behavior change. | ||
## `v1` Constraint Template | ||
|
||
In release version 3.6.0, Gatekeeper included the `v1` version of `ConstraintTemplate`. Unlike past versions of `ConstraintTemplate`, `v1` requires the Constraint schema section to be [structural](https://kubernetes.io/blog/2019/06/20/crd-structural-schema/). | ||
|
||
Structural schemas have a variety of [requirements](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#specifying-a-structural-schema). One such requirement is that the `type` field be defined for each level of the schema. | ||
|
||
For example, users of Gatekeeper may recognize the `k8srequiredlabels` ConstraintTemplate, defined here in version `v1beta1`: | ||
|
||
```yaml | ||
apiVersion: templates.gatekeeper.sh/v1beta1 | ||
kind: ConstraintTemplate | ||
metadata: | ||
name: k8srequiredlabels | ||
spec: | ||
crd: | ||
spec: | ||
names: | ||
kind: K8sRequiredLabels | ||
validation: | ||
# Schema for the `parameters` field | ||
openAPIV3Schema: | ||
properties: | ||
labels: | ||
type: array | ||
items: | ||
type: string | ||
targets: | ||
- target: admission.k8s.gatekeeper.sh | ||
rego: | | ||
package k8srequiredlabels | ||
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: %v", [missing]) | ||
} | ||
``` | ||
The `parameters` field schema (`spec.crd.spec.validation.openAPIV3Schema`) is _not_ structural. Notably, it is missing the `type:` declaration: | ||
|
||
```yaml | ||
openAPIV3Schema: | ||
# missing type | ||
properties: | ||
labels: | ||
type: array | ||
items: | ||
type: string | ||
``` | ||
|
||
This schema is _invalid_ by default in a `v1` ConstraintTemplate. Adding the `type` information makes the schema valid: | ||
|
||
```yaml | ||
openAPIV3Schema: | ||
type: object | ||
properties: | ||
labels: | ||
type: array | ||
items: | ||
type: string | ||
``` | ||
|
||
For more information on valid types in JSONSchemas, see the [JSONSchema documentation](https://json-schema.org/understanding-json-schema/reference/type.html). | ||
|
||
## Why implement this change? | ||
|
||
Structural schemas are required in version `v1` of `CustomResourceDefinition` resources, which underlie ConstraintTemplates. Requiring the same in ConstraintTemplates puts Gatekeeper in line with the overall direction of Kubernetes. | ||
|
||
Beyond this alignment, structural schemas yield significant usability improvements. The schema of a ConstraintTemplate's associated Constraint is both more visible and type validated. | ||
|
||
As the data types of Constraint fields are defined in the ConstraintTemplate, the API server will reject a Constraint with an incorrect `parameters` field. Previously, the API server would ingest it and simply not pass those `parameters` to Gatekeeper. This experience was confusing for users, and is noticeably improved by structural schemas. | ||
|
||
For example, see this incorrectly defined `k8srequiredlabels` Constraint: | ||
|
||
```yaml | ||
apiVersion: constraints.gatekeeper.sh/v1beta1 | ||
kind: K8sRequiredLabels | ||
metadata: | ||
name: ns-must-have-gk | ||
spec: | ||
match: | ||
kinds: | ||
- apiGroups: [""] | ||
kinds: ["Namespace"] | ||
parameters: | ||
# Note that "labels" is now contained in an array item, rather than an object key under "parameters" | ||
- labels: ["gatekeeper"] | ||
``` | ||
|
||
In a `v1beta1` ConstraintTemplate, this Constraint would be ingested successfully. However, it would not work. The creation of a new namespace, `foobar`, would succeed, even in the absence of the `gatekeeper` label: | ||
|
||
```shell | ||
$ kubectl create ns foobar | ||
namespace/foobar created | ||
``` | ||
|
||
This is incorrect. We'd expect this to fail: | ||
|
||
```shell | ||
$ kubectl create ns foobar | ||
Error from server ([ns-must-have-gk] you must provide labels: {"gatekeeper"}): admission webhook "validation.gatekeeper.sh" denied the request: [ns-must-have-gk] you must provide labels: {"gatekeeper"} | ||
``` | ||
|
||
The structural schema requirement _prevents this mistake_. The aforementioned `type: object` declaration would prevent the API server from accepting the incorrect `k8srequiredlabels` Constraint. | ||
|
||
```shell | ||
# Apply the Constraint with incorrect parameters schema | ||
$ cat << EOF | kubectl apply -f - | ||
apiVersion: constraints.gatekeeper.sh/v1beta1 | ||
kind: K8sRequiredLabels | ||
metadata: | ||
name: ns-must-have-gk | ||
spec: | ||
match: | ||
kinds: | ||
- apiGroups: [""] | ||
kinds: ["Namespace"] | ||
parameters: | ||
# Note that "labels" is now an array item, rather than an object | ||
- labels: ["gatekeeper"] | ||
EOF | ||
The K8sRequiredLabels "ns-must-have-gk" is invalid: spec.parameters: Invalid value: "array": spec.parameters in body must be of type object: "array" | ||
``` | ||
|
||
Fixing the incorrect `parameters` section would then yield a successful ingestion and a working Constraint. | ||
|
||
```shell | ||
$ cat << EOF | kubectl apply -f - | ||
apiVersion: constraints.gatekeeper.sh/v1beta1 | ||
kind: K8sRequiredLabels | ||
metadata: | ||
name: ns-must-have-gk | ||
spec: | ||
match: | ||
kinds: | ||
- apiGroups: [""] | ||
kinds: ["Namespace"] | ||
parameters: | ||
labels: ["gatekeeper"] | ||
EOF | ||
k8srequiredlabels.constraints.gatekeeper.sh/ns-must-have-gk created | ||
``` | ||
|
||
```shell | ||
$ kubectl create ns foobar | ||
Error from server ([ns-must-have-gk] you must provide labels: {"gatekeeper"}): admission webhook "validation.gatekeeper.sh" denied the request: [ns-must-have-gk] you must provide labels: {"gatekeeper"} | ||
``` |
71 changes: 71 additions & 0 deletions
71
website/versioned_docs/version-v3.13.x/validating-admission-policy.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
--- | ||
id: validating-admission-policy | ||
title: Integration with Kubernetes Validating Admission Policy | ||
--- | ||
|
||
`Feature State`: Gatekeeper version v3.13+ (pre-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). Do not use this feature with `validate-template-rego` flag enabled, as the policies with CEL would get rejected with Rego compilation error. | ||
## 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: | ||
- in-tree/native in-process | ||
- reduce admission request latency | ||
- improve reliability and availability | ||
- able to fail closed without impacting availability | ||
- avoid the operational burden of webhooks | ||
|
||
To reduce policy fragmentation and simplify the user experience by standardizing the policy experience. We have created an abstraction layer that provides multi-language (e.g. Rego and CEL), multi-target policy enforcement to allow for portable policies and coexistence of numerous policy implementations. | ||
|
||
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. | ||
|
||
## Example Constraint Template | ||
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) | ||
|
||
```yaml | ||
apiVersion: templates.gatekeeper.sh/v1 | ||
kind: ConstraintTemplate | ||
metadata: | ||
name: k8srequiredlabels | ||
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: "variables.params.labels.all(entry, has(object.metadata.labels) && entry.key in object.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)))" | ||
message: "regex mismatch" | ||
``` |