diff --git a/content/en/docs/reference/access-authn-authz/extensible-admission-controllers.md b/content/en/docs/reference/access-authn-authz/extensible-admission-controllers.md index f0a1a9aea2987..f0b05670fb6cd 100644 --- a/content/en/docs/reference/access-authn-authz/extensible-admission-controllers.md +++ b/content/en/docs/reference/access-authn-authz/extensible-admission-controllers.md @@ -14,7 +14,7 @@ weight: 40 {{% capture overview %}} In addition to [compiled-in admission plugins](/docs/reference/access-authn-authz/admission-controllers/), -admission plugins can be developed out-of-tree and run as webhooks configured at runtime. +admission plugins can be developed as extensions and run as webhooks configured at runtime. This page describes how to build, configure, and use admission webhooks. {{% /capture %}} @@ -28,7 +28,12 @@ and [mutating admission webhook](/docs/reference/access-authn-authz/admission-controllers/#mutatingadmissionwebhook). Mutating admission Webhooks are invoked first, and can modify objects sent to the API server to enforce custom defaults. After all object modifications are complete, and after the incoming object is validated by the API server, -validating admission Webhooks are invoked and can reject requests to enforce custom policies. +validating admission webhooks are invoked and can reject requests to enforce custom policies. + +{{< note >}} +Admission webhooks that need to guarantee they see the final state of the object in order to enforce policy +should use a validating admission webhook, since objects can be modified after being seen by mutating webhooks. +{{< /note >}} ## Experimenting with admission webhooks @@ -88,7 +93,7 @@ or [MutatingWebhookConfiguration](https://github.com/kubernetes/kubernetes/blob/v1.13.0/staging/src/k8s.io/api/admissionregistration/v1beta1/types.go#L114). The following is an example `validatingWebhookConfiguration`, a mutating webhook -configuration is similar. See the [API reference](#api-reference) for details about all fields. +configuration is similar. See the [webhook configuration](#webhook-configuration) section for details about each config field. ```yaml apiVersion: admissionregistration.k8s.io/v1beta1 @@ -172,6 +177,7 @@ plugins: The schema of `admissionConfiguration` is defined [here](https://github.com/kubernetes/kubernetes/blob/v1.13.0/staging/src/k8s.io/apiserver/pkg/apis/apiserver/v1alpha1/types.go#L27). +See the [webhook configuration](#webhook-configuration) section for details about each config field. * In the kubeConfig file, provide the credentials: @@ -198,6 +204,188 @@ users: Of course you need to set up the webhook server to handle these authentications. +## Webhook request and response + +### Request + +Webhooks are sent a POST request, with `Content-Type: application/json`, +with an `AdmissionReview` API object in the `admission.k8s.io` API group +serialized to JSON as the body. + +Webhooks can specify what versions of `AdmissionReview` objects they accept +with the `admissionReviewVersions` field in their configuration: + +```yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +... +webhooks: +- name: my-webhook.example.com + admissionReviewVersions: ["v1beta1"] + ... +``` + +If no `admissionReviewVersions` are specified, the default when creating +`admissionregistration.k8s.io/v1beta1` webhook configurations is `v1beta1`. + +API servers send the first `AdmissionReview` version in the `admissionReviewVersions` list they support. +If none of the versions in the list are supported by the API server, the configuration will not be allowed to be created. +If an API server encounters a webhook configuration that was previously created and does not support any of the `AdmissionReview` +versions the API server knows how to send, attempts to call to the webhook will fail and be subject to the [failure policy](#failure-policy). + +This example shows the data contained in an `AdmissionReview` object +for a request to update the `scale` subresource of an `apps/v1` `Deployment`: + +```json +{ + "apiVersion": "admission.k8s.io/v1beta1", + "kind": "AdmissionReview", + "request": { + // Random uid uniquely identifying this admission call + "uid": "705ab4f5-6393-11e8-b7cc-42010a800002", + + // Fully-qualified group/version/kind of the incoming object + "kind": {"group":"autoscaling","version":"v1","kind":"Scale"}, + // Fully-qualified group/version/kind of the resource being modified + "resource": {"group":"apps","version":"v1","resource":"deployments"}, + // subresource, if the request is to a subresource + "subResource": "scale", + + // Fully-qualified group/version/kind of the incoming object in the original request to the API server. + // This only differs from `kind` if the webhook specified `matchPolicy: Equivalent` and the + // original request to the API server was converted to a version the webhook registered for. + // Only sent by v1.15+ API servers. + "requestKind": {"group":"autoscaling","version":"v1","kind":"Scale"}, + // Fully-qualified group/version/kind of the resource being modified in the original request to the API server. + // This only differs from `resource` if the webhook specified `matchPolicy: Equivalent` and the + // original request to the API server was converted to a version the webhook registered for. + // Only sent by v1.15+ API servers. + "requestResource": {"group":"apps","version":"v1","resource":"deployments"}, + // subresource, if the request is to a subresource + // This only differs from `subResource` if the webhook specified `matchPolicy: Equivalent` and the + // original request to the API server was converted to a version the webhook registered for. + // Only sent by v1.15+ API servers. + "requestSubResource": "scale", + + // Name of the resource being modified + "name": "my-deployment", + // Namespace of the resource being modified, if the resource is namespaced (or is a Namespace object) + "namespace": "my-namespace", + + // operation can be CREATE, UPDATE, DELETE, or CONNECT + "operation": "UPDATE", + + "userInfo": { + // Username of the authenticated user making the request to the API server + "username": "admin", + // UID of the authenticated user making the request to the API server + "uid": "014fbff9a07c", + // Group memberships of the authenticated user making the request to the API server + "groups": ["system:authenticated","my-admin-group"], + // Arbitrary extra info associated with the user making the request to the API server. + // This is populated by the API server authentication layer and should be included + // if any SubjectAccessReview checks are performed by the webhook. + "extra": { + "some-key":["some-value1", "some-value2"] + } + }, + + // object is the new object being admitted. + // It is null for DELETE operations. + "object": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, + // oldObject is the existing object. + // It is null for CREATE and CONNECT operations (and for DELETE operations in API servers prior to v1.15.0) + "oldObject": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, + // options contains the options for the operation being admitted, like meta.k8s.io/v1 CreateOptions, UpdateOptions, or DeleteOptions. + // It is null for CONNECT operations. + // Only sent by v1.15+ API servers. + "options": {"apiVersion":"meta.k8s.io/v1","kind":"UpdateOptions",...}, + + // dryRun indicates the API request is running in dry run mode and will not be persisted. + // Webhooks with side effects should avoid actuating those side effects when dryRun is true. + // See http://k8s.io/docs/reference/using-api/api-concepts/#make-a-dry-run-request for more details. + "dryRun": false + } +} +``` + +### Response + +Webhooks respond with a 200 HTTP status code, `Content-Type: application/json`, +and a body containing an `AdmissionReview` object (in the same version they were sent), +with the `response` stanza populated, serialized to JSON. + +At a minimum, the `response` stanza must contain the following fields: +* `uid`, copied from the `request.uid` sent to the webhook +* `allowed`, either set to `true` or `false` + +Example of a minimal response from a webhook to allow a request: +```json +{ + "apiVersion": "admission.k8s.io/v1beta1", + "kind": "AdmissionReview", + "response": { + "uid": "", + "allowed": true + } +} +``` + +Example of a minimal response from a webhook to forbid a request: +```json +{ + "apiVersion": "admission.k8s.io/v1beta1", + "kind": "AdmissionReview", + "response": { + "uid": "", + "allowed": false + } +} +``` + +When rejecting a request, the webhook can customize the http code and message returned to the user using the `status` field. +The specified status object is returned to the user. +See [API documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#status-v1-meta) for details about the status type. +Example of a response to forbid a request, customizing the HTTP status code and message presented to the user: +```json +{ + "apiVersion": "admission.k8s.io/v1beta1", + "kind": "AdmissionReview", + "response": { + "uid": "", + "allowed": false, + "status": { + "code": 403, + "message": "You cannot do this because it is Tuesday and your name starts with A" + } + } +} +``` + +When allowing a request, a mutating admission webhook may optionally modify the incoming object as well. +This is done using the `patch` and `patchType` fields in the response. +The only currently supported `patchType` is `JSONPatch`. +See [JSON patch](http://jsonpatch.com/) documentation for more details. +For `patchType: JSONPatch`, the `patch` field contains a base64-encoded array of JSON patch operations. + +As an example, a single patch operation that would add a label would be `[{"op": "add", "path": "/metadata/labels/mylabel", "value": "myvalue"}]` + +Base64-encoded, this would be `W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL21ldGFkYXRhL2xhYmVscy9teWxhYmVsIiwgInZhbHVlIjogIm15dmFsdWUifV0=` + +So a webhook response to add that label would be: +```json +{ + "apiVersion": "admission.k8s.io/v1beta1", + "kind": "AdmissionReview", + "response": { + "uid": "", + "allowed": true, + "patchType": "JSONPatch", + "patch": "W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL21ldGFkYXRhL2xhYmVscy9teWxhYmVsIiwgInZhbHVlIjogIm15dmFsdWUifV0=" + } +} +``` + ## Webhook configuration To register admission webhooks, create `MutatingWebhookConfiguration` or `ValidatingWebhookConfiguration` API objects. @@ -206,9 +394,26 @@ Each configuration can contain one or more webhooks. Each webhook defines the fo ### Matching requests: rules Each webhook must specify a list of rules used to determine if a request to the API server should be sent to the webhook. -These rules specify one or more operations, API groups/versions/resources, and a resource scope. +Each rule specifies one or more operations, apiGroups, apiVersions, and resources, and a resource scope: + +* `operations` lists one or more operations to match. Can be `"CREATE"`, `"UPDATE"`, `"DELETE"`, `"CONNECT"`, or `"*"` to match all. +* `apiGroups` lists one or more API groups to match. `""` is the core API group. `"*"` matches all API groups. +* `apiVersions` lists one or more API versions to match. `"*"` matches all API versions. +* `resources` lists one or more resources to match. + * `"*"` matches all resources, but not subresources. + * `"*/*"` matches all resources and subresources. + * `"pods/*"` matches all subresources of pods. + * `"*/status"` matches all status subresources. +* `scope` specifies a scope to match. Valid values are `"Cluster"`, `"Namespaced"`, and `"*"`. Subresources match the scope of their parent resource. Supported in v1.14+. Default is `"*"`, matching pre-1.14 behavior. + * `"Cluster"` means that only cluster-scoped resources will match this rule (Namespace API objects are cluster-scoped). + * `"Namespaced"` means that only namespaced resources will match this rule. + * `"*"` means that there are no scope restrictions. + If an incoming request matches one of the specified operations, groups, versions, resources, and scope for any of a webhook's rules, the request is sent to the webhook. -This example shows a rule for a validating webhook that would match `CREATE` or `UPDATE` requests to `apps/v1` and `apps/v1beta1` `deployments` and `replicasets`: + +Here are other examples of rules that could be used to specify which resources should be intercepted. + +Match `CREATE` or `UPDATE` requests to `apps/v1` and `apps/v1beta1` `deployments` and `replicasets`: ```yaml apiVersion: admissionregistration.k8s.io/v1beta1 @@ -217,27 +422,46 @@ kind: ValidatingWebhookConfiguration webhooks: - name: my-webhook.example.com rules: - - # operations lists one or more operations to match. Can be CREATE, UPDATE, DELETE, CONNECT, or "*" to match all. - operations: ["CREATE", "UPDATE"] - # apiGroups lists one or more API groups to match. "" is the core API group. "*" matches all API groups. + - operations: ["CREATE", "UPDATE"] apiGroups: ["apps"] - # apiVersions lists one or more API versions to match. "*" matches all API versions. apiVersions: ["v1", "v1beta1"] - # resources lists one or more resources to match. - # "*" matches all resources, but not subresources. - # "*/*" matches all resources and subresources. - # "pods/*" matches all subresources of pods. - # "*/status" matches all status subresources. resources: ["deployments", "replicasets"] - # scope specifies a scope to match. - # Valid values are "Cluster", "Namespaced", and "*" - # "Cluster" means that only cluster-scoped resources will match this rule (Namespace API objects are cluster-scoped). - # "Namespaced" means that only namespaced resources will match this rule. - # "*" means that there are no scope restrictions. - # Subresources match the scope of their parent resource. - # Supported in v1.14+. - # Default is "*", matching pre-1.14 behavior. scope: "Namespaced" + ... +``` + +Match create requests for all resources (but not subresources) in all API groups and versions: + +```yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +... +webhooks: +- name: my-webhook.example.com + rules: + - operations: ["CREATE"] + apiGroups: ["*"] + apiVersions: ["*"] + resources: ["*"] + scope: "*" + ... +``` + +Match update requests for all `status` subresources in all API groups and versions: + +```yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +... +webhooks: +- name: my-webhook.example.com + rules: + - operations: ["UPDATE"] + apiGroups: ["*"] + apiVersions: ["*"] + resources: ["*/status"] + scope: "*" + ... ``` ### Matching requests: objectSelector @@ -270,6 +494,7 @@ webhooks: apiVersions: ["*"] resources: ["*"] scope: "*" + ... ``` See https://kubernetes.io/docs/concepts/overview/working-with-objects/labels for more examples of label selectors. @@ -304,10 +529,11 @@ webhooks: apiVersions: ["*"] resources: ["*"] scope: "Namespaced" + ... ``` This example shows a validating webhook that matches a `CREATE` of any namespaced resource inside a namespace -that associated with the "environment" of "prod" or "staging": +that is associated with the "environment" of "prod" or "staging": ```yaml apiVersion: admissionregistration.k8s.io/v1beta1 @@ -326,30 +552,39 @@ webhooks: apiVersions: ["*"] resources: ["*"] scope: "Namespaced" + ... ``` See https://kubernetes.io/docs/concepts/overview/working-with-objects/labels for more examples of label selectors. ### Matching requests: matchPolicy -In v1.15+, `matchPolicy` lets a webhook defines how the `rules` list in its configuration is used to match incoming requests. +API servers can make objects available via multiple API groups or versions. +For example, the Kubernetes API server allows creating and modifying `Deployment` objects +via `extensions/v1beta1`, `apps/v1beta1`, `apps/v1beta2`, and `apps/v1` APIs. + +For example, if a webhook only specified a rule for some API groups/versions (like `apiGroups:["apps"], apiVersions:["v1","v1beta1"]`), +and a request was made to modify the resource via another API group/version (like `extensions/v1beta1`), +the request would not be sent to the webhook. + +In v1.15+, `matchPolicy` lets a webhook define how its `rules` are used to match incoming requests. Allowed values are `Exact` or `Equivalent`. The default in `v1beta1` is `Exact`. * `Exact` means a request should be intercepted only if it exactly matches a specified rule. * `Equivalent` means a request should be intercepted if modifies a resource listed in `rules`, even via another API group or version. -API servers can make objects available via multiple API groups or versions. -For example, the Kubernetes API server allows creating and modifying `Deployment` objects -via `extensions/v1beta1`, `apps/v1beta1`, `apps/v1beta2`, and `apps/v1` APIs. +In the example given above, the webhook that only registered for `apps/v1` could use `matchPolicy`: +* `matchPolicy: Exact` would mean the `extensions/v1beta1` request would not be sent to the webhook +* `matchPolicy: Equivalent` means the `extensions/v1beta1` request would be sent to the webhook (with the objects converted to a version the webhook had specified: `apps/v1`) -If a webhook only specified a rule for some API groups/versions (like `apiGroups:["apps"], apiVersions:["v1","v1beta1"]`), -and a request was made to modify the resource via another API group/version (like `extensions/v1beta1`): -* `matchPolicy: Exact` means the request would not be sent to the webhook -* `matchPolicy: Equivalent` means the request would be sent to the webhook (with the objects converted to a version the webhook had specified, like `apps/v1`) +Specifying `Equivalent` is recommended, and ensures that webhooks continue to intercept the +resources they expect when upgrades enable new versions of the resource in the API server. -Specifying `Equivalent` means a webhook only needs to register for and understand a single version of a resource. -It ensures that webhooks continue to intercept the resources they expect when upgrades enable new versions of the resource in the API server. -This is generally recommended, and `matchPolicy: Equivalent` will likely to be the default in future versions. +When a resource stops being served by the API server, it is no longer considered equivalent to other versions of that resource that are still served. +For example, deprecated `extensions/v1beta1` deployments are scheduled to stop being served by default in v1.16. +Once that occurs, a webhook with a `apiGroups:["extensions"], apiVersions:["v1beta1"], resources:["deployments"]` rule +would no longer intercept deployments created via `apps/v1` APIs. For that reason, webhooks should prefer registering +for stable versions of resources. This example shows a validating webhook that intercepts modifications to deployments (no matter the API group or version), and is always sent an `apps/v1` `Deployment` object: @@ -367,49 +602,9 @@ webhooks: apiVersions: ["v1"] resources: ["deployments"] scope: "Namespaced" + ... ``` -### Matching requests: examples - -Here are other examples of rules that could be used to specify which resources should be intercepted. - -* Match create requests for all resources (but not subresources) in all API groups and versions: - - ```yaml - rules: - - operations: ["CREATE"] - apiGroups: ["*"] - apiVersions: ["*"] - resources: ["*"] - scope: "*" - ``` - -* Match update requests for all `status` subresources in all API groups and versions: - - ```yaml - rules: - - operations: ["UPDATE"] - apiGroups: ["*"] - apiVersions: ["*"] - resources: ["*/status"] - scope: "*" - ``` - -* Match create, update, and delete requests for `apps/v1` `deployments`, -and if create/update/delete requests are made for `deployments` in other API groups or versions, -(like `extensions/v1beta1` or `apps/v1beta1`), call the webhook with the `apps/v1` versions of those objects: - - ```yaml - # matchPolicy is available in Kubernetes v1.15+ - matchPolicy: Equivalent - rules: - - operations: ["CREATE","UPDATE","DELETE"] - apiGroups: ["apps"] - apiVersions: ["v1"] - resources: ["deployments"] - scope: "*" - ``` - ### Contacting the webhook Once the API server has determined a request should be sent to a webhook, @@ -438,13 +633,8 @@ to turn up in a new cluster. The scheme must be "https"; the URL must begin with "https://". -A path is optional, and if present may be any string permissible in -a URL. You may use the path to pass an arbitrary string to the -webhook, for example, a cluster identifier. - -Attempting to use a user or basic auth e.g. "user:password@" is not -allowed. Fragments ("#...") and query parameters ("?...") are also not -allowed. +Attempting to use a user or basic auth e.g. "user:password@" is not allowed. +Fragments ("#...") and query parameters ("?...") are also not allowed. Here is an example of a mutating webhook configured to call a URL (and expects the TLS certificate to be verified using system trust roots, so does not specify a caBundle): @@ -455,7 +645,7 @@ kind: MutatingWebhookConfiguration webhooks: - name: my-webhook.example.com clientConfig: - url: "https://my-webhook.example.com:9443" + url: "https://my-webhook.example.com:9443/my-webhook-path" ... ``` @@ -514,17 +704,22 @@ webhooks: ### Reinvocation policy -TODO: reinvocationPolicy docs and examples +A single ordering of mutating admissions plugins (including webhooks) does not work for all cases +(see https://issue.k8s.io/64333 as an example). A mutating webhook can add a new sub-structure +to the object (like adding a `container` to a `pod`), and other mutating plugins which have already +run may have opinions on those new structures (like setting an `imagePullPolicy` on all containers). -### Failure policy +In v1.15+, to allow mutating admission plugins to observe changes made by other plugins, +built-in mutating admission plugins are re-run at least once if a mutating webhook modifies an object, +and mutating webhooks can specify a `reinvocationPolicy` to control whether they are reinvoked as well. -`failurePolicy` defines how unrecognized errors (including timeout errors) from the admission webhook -are handled. Allowed values are `Ignore` or `Fail`. Defaults to `Ignore` in v1beta1. +`reinvocationPolicy` may be set to `Never` or `IfNeeded`. It defaults to `Never`. -* `Ignore` means that an error calling the webhook is ignored and the API request is allowed to continue. -* `Fail` means that an error calling the webhook causes the admission to fail and the API request to be rejected. +* `Never`: the webhook must not be called more than once in a single admission evaluation +* `IfNeeded`: the webhook may be called at least one additional time as part of the admission +evaluation if the object being admitted is modified by other admission plugins after the initial webhook call. -Here is a mutating webhook configured to fail admission if errors are encountered during invocation: +Here is an example of a mutating webhook opting into being re-invoked if later admission plugins modify the object: ```yaml apiVersion: admissionregistration.k8s.io/v1beta1 @@ -532,188 +727,28 @@ kind: MutatingWebhookConfiguration ... webhooks: - name: my-webhook.example.com - failurePolicy: Fail + reinvocationPolicy: IfNeeded ... ``` -## Webhook request and response +### Failure policy -### Request +`failurePolicy` defines how unrecognized errors and timeout errors from the admission webhook +are handled. Allowed values are `Ignore` or `Fail`. Defaults to `Ignore` in v1beta1. -Webhooks are sent a POST request, with `Content-Type: application/json`, -with an `AdmissionReview` API object in the `admission.k8s.io` API group -serialized to JSON as the body. +* `Ignore` means that an error calling the webhook is ignored and the API request is allowed to continue. +* `Fail` means that an error calling the webhook causes the admission to fail and the API request to be rejected. -Webhooks can specify what versions of `AdmissionReview` objects they accept -with the `admissionReviewVersions` field in their configuration: +Here is a mutating webhook configured to reject an API request if errors are encountered calling the admission webhook: ```yaml apiVersion: admissionregistration.k8s.io/v1beta1 -kind: ValidatingWebhookConfiguration +kind: MutatingWebhookConfiguration ... webhooks: - name: my-webhook.example.com - admissionReviewVersions: ["v1beta1"] + failurePolicy: Fail ... ``` -If no `admissionReviewVersions` are specified, the default when creating -`admissionregistration.k8s.io/v1beta1` webhook configurations is `v1beta1`. - -API servers send the first `AdmissionReview` version in the `admissionReviewVersions` list they support. -If none of the versions in the list are supported by the API server, the configuration will not be allowed to be created. -If the webhook configuration has already been persisted, attempts to call to the webhook will fail and be subject to the [failure policy](#failure-policy). - -This example shows the data contained in an `AdmissionReview` object -for a request to update the `scale` subresource of an `apps/v1` `Deployment`: - -```json -{ - "apiVersion": "admission.k8s.io/v1beta1", - "kind": "AdmissionReview", - "request": { - // Random uid uniquely identifying this admission call - "uid": "705ab4f5-6393-11e8-b7cc-42010a800002", - - // Fully-qualified group/version/kind of the incoming object - "kind": {"group":"autoscaling","version":"v1","kind":"Scale"}, - // Fully-qualified group/version/kind of the resource being modified - "resource": {"group":"apps","version":"v1","resource":"deployments"}, - // subresource, if the request is to a subresource - "subResource": "scale", - - // Fully-qualified group/version/kind of the incoming object in the original request to the API server. - // This only differs from `kind` if the webhook specified `matchPolicy: Equivalent` and the - // original request to the API server was converted to a version the webhook registered for. - // Only sent by v1.15+ API servers. - "requestKind": {"group":"autoscaling","version":"v1","kind":"Scale"}, - // Fully-qualified group/version/kind of the resource being modified in the original request to the API server. - // This only differs from `resource` if the webhook specified `matchPolicy: Equivalent` and the - // original request to the API server was converted to a version the webhook registered for. - // Only sent by v1.15+ API servers. - "requestResource": {"group":"apps","version":"v1","resource":"deployments"}, - // subresource, if the request is to a subresource - // This only differs from `subResource` if the webhook specified `matchPolicy: Equivalent` and the - // original request to the API server was converted to a version the webhook registered for. - // Only sent by v1.15+ API servers. - "requestSubResource": "scale", - - // Name of the resource being modified - "name": "my-deployment", - // Namespace of the resource being modified, if the resource is namespaced (or is a Namespace object) - "namespace": "my-namespace", - - // operation can be CREATE, UPDATE, DELETE, or CONNECT - "operation": "UPDATE", - - "userInfo": { - // Username of the authenticated user making the request to the API server - "username": "admin", - // UID of the authenticated user making the request to the API server - "uid": "014fbff9a07c", - // Group memberships of the authenticated user making the request to the API server - "groups": ["system:authenticated","my-admin-group"], - // Arbitrary extra info associated with the user making the request to the API server. - // This is populated by the API server authentication layer and should be included - // if any SubjectAccessReview checks are performed by the webhook. - "extra": { - "some-key":["some-value1", "some-value2"] - } - }, - - // object is the new object being admitted. - // It is null for DELETE operations. - "object": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, - // oldObject is the existing object. - // It is null for CREATE and CONNECT operations (and for DELETE operations in API servers prior to v1.15.0) - "oldObject": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, - // options contains the options for the operation being admitted, like meta.k8s.io/v1 CreateOptions, UpdateOptions, or DeleteOptions. - // It is null for CONNECT operations. - // Only sent by v1.15+ API servers. - "options": {"apiVersion":"meta.k8s.io/v1","kind":"UpdateOptions",...}, - - // dryRun indicates the API request is running in dry run mode and will not be persisted. - // Webhooks with side effects should avoid actuating those side effects when dryRun is true. - "dryRun": false - } -} -``` - -### Response - -Webhooks respond with a 200 HTTP status code, `Content-Type: application/json`, -and a body containing an `AdmissionReview` object (in the same version they were sent), -with the `response` stanza populated, serialized to JSON. - -At a minimum, the `response` stanza must contain the following fields: -* `uid`, copied from the `request.uid` sent to the webhook -* `allowed`, either set to `true` or `false` - -Example of a minimal response from a webhook to allow a request: -```json -{ - "apiVersion": "admission.k8s.io/v1beta1", - "kind": "AdmissionReview", - "response": { - "uid": "", - "allowed": true - } -} -``` - -Example of a minimal response from a webhook to forbid a request: -```json -{ - "apiVersion": "admission.k8s.io/v1beta1", - "kind": "AdmissionReview", - "response": { - "uid": "", - "allowed": false - } -} -``` - -When rejecting a request, the webhook can customize the http code and message returned to the user using the `status` field. -The specified status object is returned to the user. -See [API documentation](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.14/#status-v1-meta) for details about the status type. -Example of a response to forbid a request, customizing the HTTP status code and message presented to the user: -```json -{ - "apiVersion": "admission.k8s.io/v1beta1", - "kind": "AdmissionReview", - "response": { - "uid": "", - "allowed": false, - "status": { - "code": 403, - "message": "You cannot do this because it is Tuesday and your name starts with A" - } - } -} -``` - -When allowing a request, a mutating admission webhook may optionally modify the incoming object as well. -This is done using the `patch` and `patchType` fields in the response. -The only currently supported `patchType` is `JSONPatch`. -See [JSON patch](http://jsonpatch.com/) documentation for more details. -For `patchType: JSONPatch`, the `patch` field contains a base64-encoded array of JSON patch operations. - -As an example, a single patch operation that would add a label would be `[{"op": "add", "path": "/metadata/labels/mylabel", "value": "myvalue"}]` - -Base64-encoded, this would be `W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL21ldGFkYXRhL2xhYmVscy9teWxhYmVsIiwgInZhbHVlIjogIm15dmFsdWUifV0=` - -So a webhook response to add that label would be: -```json -{ - "apiVersion": "admission.k8s.io/v1beta1", - "kind": "AdmissionReview", - "response": { - "uid": "", - "allowed": true, - "patchType": "JSONPatch", - "patch": "W3sib3AiOiAiYWRkIiwgInBhdGgiOiAiL21ldGFkYXRhL2xhYmVscy9teWxhYmVsIiwgInZhbHVlIjogIm15dmFsdWUifV0=" - } -} -``` - {{% /capture %}}