|
| 1 | +# kubernetesValidating |
| 2 | + |
| 3 | +This binding transforms a hook into a handler for ValidatingWebhookConfiguration. The Shell-operator creates ValidatingWebhookConfiguration, starts HTTPS server, and runs hooks to handle [AdmissionReview requests](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#request). |
| 4 | + |
| 5 | +> Note: shell-operator use `admissionregistration.k8s.io/v1`, so Kubernetes 1.16+ is needed. |
| 6 | +
|
| 7 | +## Syntax |
| 8 | + |
| 9 | +```yaml |
| 10 | +configVersion: v1 |
| 11 | +onStartup: 10 |
| 12 | +kubernetes: |
| 13 | +- name: myCrdObjects |
| 14 | + ... |
| 15 | +kubernetesValidating: |
| 16 | +- name: my-crd-validator.example.com |
| 17 | + # include snapshots by binding names |
| 18 | + includeSnapshotsFrom: ["myCrdObjects"] |
| 19 | + # or use group name to include all snapshots in a group |
| 20 | + group: "group name" |
| 21 | + labelSelector: # equivalent of objectSelector |
| 22 | + matchLabels: |
| 23 | + label1: value1 |
| 24 | + ... |
| 25 | + namespace: |
| 26 | + labelSelector: # equivalent of namespaceSelector |
| 27 | + matchLabels: |
| 28 | + label1: value1 |
| 29 | + ... |
| 30 | + matchExpressions: |
| 31 | + - key: environment |
| 32 | + operator: In |
| 33 | + values: ["prod","staging"] |
| 34 | + rules: |
| 35 | + - apiVersions: |
| 36 | + - v1 |
| 37 | + apiGroups: |
| 38 | + - stable.example.com |
| 39 | + resources: |
| 40 | + - CronTab |
| 41 | + operations: |
| 42 | + - "*" |
| 43 | + - operations: ["CREATE", "UPDATE"] |
| 44 | + apiGroups: ["apps"] |
| 45 | + apiVersions: ["v1", "v1beta1"] |
| 46 | + resources: ["deployments", "replicasets"] |
| 47 | + scope: "Namespaced" |
| 48 | + failurePolicy: Ignore | Fail (default) |
| 49 | + sideEffects: None (default) | NoneOnDryRun |
| 50 | + timeoutSeconds: 2 (default is 10) |
| 51 | +``` |
| 52 | +
|
| 53 | +## Parameters |
| 54 | +
|
| 55 | +- `name` — a required parameter. It should be a domain with at least three segments separated by dots. |
| 56 | + |
| 57 | +- `includeSnapshotsFrom` — an array of names of `kubernetes` bindings in a hook. When specified, a list of monitored objects from these bindings will be added to the binding context in the `snapshots` field. |
| 58 | + |
| 59 | +- `group` — a key to include snapshots from a group of `schedule` and `kubernetes` bindings. See [grouping](#an-example-of-a-binding-context-with-group). |
| 60 | + |
| 61 | +- `labelSelector` — [standard](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#labelselector-v1-meta) selector of objects by labels (examples [of use](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels)). See [objectSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-objectselector). |
| 62 | + |
| 63 | +- `namespace.labelSelector` — this filter works like `labelSelector` but for namespaces. See [namespaceSelector](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-namespaceselector). |
| 64 | + |
| 65 | +- `rules` — a required list of rules used to determine if a request to the Kubernetes API server should be sent to the hook. See [Rules](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-rules). |
| 66 | + |
| 67 | +- `failurePolicy` — defines how errors from the hook are handled. See [Failure policy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#failure-policy). Default is `Fail`. |
| 68 | + |
| 69 | +- `sideEffects` — determine whether the hook is `dryRun`-aware. See [side effects](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#side-effects) documentation. Default is `None`. |
| 70 | + |
| 71 | +- `timeoutSeconds` — a seconds API server should wait for a hook to respond before treating the call as a failure. See [timeouts](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#timeouts). Default is 10 (seconds). |
| 72 | + |
| 73 | +As you can see, it is the close copy of a [Webhook configuration](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#webhook-configuration). Differences are: |
| 74 | +- `objectSelector` is a `labelSelector` as in the `kubernetes` binding. |
| 75 | +- `namespaceSelector` is a `namespace.labelSelector` as in the `kubernetes` binding. |
| 76 | +- `clientConfig` is managed by the Shell-operator. You should provide a Service for the Shell-operator HTTPS endpoint. See example [204-validating-webhook](./examples/204-validating-webhook) for possible solution. |
| 77 | +- `matchPolicy` is always "Equivalent". See [Matching requests: matchPolicy](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-matchpolicy). |
| 78 | +- there are additional fields `group` and `includeSnapshotsFrom` to include snapshots in the binding context. |
| 79 | + |
| 80 | +## Example |
| 81 | + |
| 82 | +``` |
| 83 | +configVersion: v1 |
| 84 | +kubernetesValidating: |
| 85 | +- name: private-repo-policy.example.com |
| 86 | + rules: |
| 87 | + - apiGroups: ["stable.example.com"] |
| 88 | + apiVersions: ["v1"] |
| 89 | + operations: ["CREATE"] |
| 90 | + resources: ["crontabs"] |
| 91 | + scope: "Namespaced" |
| 92 | +``` |
| 93 | +
|
| 94 | +The Shell-operator will execute hook with this configuration on every creation of CronTab object. |
| 95 | +
|
| 96 | +See example [204-validating-webhook](./examples/204-validating-webhook). |
| 97 | +
|
| 98 | +## Hook input and output |
| 99 | +
|
| 100 | +> Note that the `group` parameter is only for including snapshots. `kubernetesValidating` hook is never executed on `schedule` or `kubernetes` events with binding context with `"type":"Group"`. |
| 101 | +
|
| 102 | +The hook receives a binding context and should return response in `$VALIDATING_RESPONSE_PATH`. |
| 103 | +
|
| 104 | +$BINDING_CONTEXT_PATH file example: |
| 105 | +
|
| 106 | +```yaml |
| 107 | +[{ |
| 108 | +# Name as defined in binding configuration. |
| 109 | +"binding": "my-crd-validator.example.com", |
| 110 | +# Validating to distinguish from other events. |
| 111 | +"type": "Validating", |
| 112 | +# Snapshots as defined by includeSnapshotsFrom or group. |
| 113 | +"snapshots": { ... } |
| 114 | +# AdmissionReview object. |
| 115 | +"review": { |
| 116 | + "apiVersion": "admission.k8s.io/v1", |
| 117 | + "kind": "AdmissionReview", |
| 118 | + "request": { |
| 119 | + # Random uid uniquely identifying this admission call |
| 120 | + "uid": "705ab4f5-6393-11e8-b7cc-42010a800002", |
| 121 | +
|
| 122 | + # Fully-qualified group/version/kind of the incoming object |
| 123 | + "kind": {"group":"autoscaling","version":"v1","kind":"Scale"}, |
| 124 | + # Fully-qualified group/version/kind of the resource being modified |
| 125 | + "resource": {"group":"apps","version":"v1","resource":"deployments"}, |
| 126 | + # subresource, if the request is to a subresource |
| 127 | + "subResource": "scale", |
| 128 | +
|
| 129 | + # Fully-qualified group/version/kind of the incoming object in the original request to the API server. |
| 130 | + # This only differs from `kind` if the webhook specified `matchPolicy: Equivalent` and the |
| 131 | + # original request to the API server was converted to a version the webhook registered for. |
| 132 | + "requestKind": {"group":"autoscaling","version":"v1","kind":"Scale"}, |
| 133 | + # Fully-qualified group/version/kind of the resource being modified in the original request to the API server. |
| 134 | + # This only differs from `resource` if the webhook specified `matchPolicy: Equivalent` and the |
| 135 | + # original request to the API server was converted to a version the webhook registered for. |
| 136 | + "requestResource": {"group":"apps","version":"v1","resource":"deployments"}, |
| 137 | + # subresource, if the request is to a subresource |
| 138 | + # This only differs from `subResource` if the webhook specified `matchPolicy: Equivalent` and the |
| 139 | + # original request to the API server was converted to a version the webhook registered for. |
| 140 | + "requestSubResource": "scale", |
| 141 | +
|
| 142 | + # Name of the resource being modified |
| 143 | + "name": "my-deployment", |
| 144 | + # Namespace of the resource being modified, if the resource is namespaced (or is a Namespace object) |
| 145 | + "namespace": "my-namespace", |
| 146 | +
|
| 147 | + # operation can be CREATE, UPDATE, DELETE, or CONNECT |
| 148 | + "operation": "UPDATE", |
| 149 | +
|
| 150 | + "userInfo": { |
| 151 | + # Username of the authenticated user making the request to the API server |
| 152 | + "username": "admin", |
| 153 | + # UID of the authenticated user making the request to the API server |
| 154 | + "uid": "014fbff9a07c", |
| 155 | + # Group memberships of the authenticated user making the request to the API server |
| 156 | + "groups": ["system:authenticated","my-admin-group"], |
| 157 | + # Arbitrary extra info associated with the user making the request to the API server. |
| 158 | + # This is populated by the API server authentication layer and should be included |
| 159 | + # if any SubjectAccessReview checks are performed by the webhook. |
| 160 | + "extra": { |
| 161 | + "some-key":["some-value1", "some-value2"] |
| 162 | + } |
| 163 | + }, |
| 164 | +
|
| 165 | + # object is the new object being admitted. |
| 166 | + # It is null for DELETE operations. |
| 167 | + "object": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, |
| 168 | + # oldObject is the existing object. |
| 169 | + # It is null for CREATE and CONNECT operations. |
| 170 | + "oldObject": {"apiVersion":"autoscaling/v1","kind":"Scale",...}, |
| 171 | + # options contains the options for the operation being admitted, like meta.k8s.io/v1 CreateOptions, UpdateOptions, or DeleteOptions. |
| 172 | + # It is null for CONNECT operations. |
| 173 | + "options": {"apiVersion":"meta.k8s.io/v1","kind":"UpdateOptions",...}, |
| 174 | +
|
| 175 | + # dryRun indicates the API request is running in dry run mode and will not be persisted. |
| 176 | + # Webhooks with side effects should avoid actuating those side effects when dryRun is true. |
| 177 | + # See http://k8s.io/docs/reference/using-api/api-concepts/#make-a-dry-run-request for more details. |
| 178 | + "dryRun": false |
| 179 | + } |
| 180 | +} |
| 181 | +}] |
| 182 | +``` |
| 183 | + |
| 184 | +Response example: |
| 185 | +``` |
| 186 | +cat <<EOF > $VALIDATING_RESPONSE_PATH |
| 187 | +{"allowed": true} |
| 188 | +EOF |
| 189 | +``` |
| 190 | + |
| 191 | +Deny object creation and explain why: |
| 192 | +``` |
| 193 | +cat <<EOF > $VALIDATING_RESPONSE_PATH |
| 194 | +{"allowed": false, "message": "You cannot do this because it is Tuesday and your name starts with A"} |
| 195 | +EOF |
| 196 | +``` |
| 197 | + |
| 198 | +User will see an error message: |
| 199 | + |
| 200 | +``` |
| 201 | +Error from server: admission webhook "policy.example.com" denied the request: You cannot do this because it is Tuesday and your name starts with A |
| 202 | +``` |
| 203 | + |
| 204 | +Empty or invalid $VALIDATING_RESPONSE_PATH file is considered as `"allowed": false` with a short message about the problem and a more verbose error in the log. |
| 205 | + |
| 206 | +## HTTP server and Kubernetes configuration |
| 207 | + |
| 208 | +Shell-operator should create an HTTP endpoint with TLS support and register endpoints in the ValidatingWebhookConfiguration resource. |
| 209 | + |
| 210 | +There should be a Service for shell-operator (see [Availability](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#availability)). |
| 211 | + |
| 212 | +Command line options: |
| 213 | + |
| 214 | +``` |
| 215 | +--validating-webhook-server-cert="/validating-certs/cert.crt" |
| 216 | + A path to a server certificate for ValidatingWebhook. Can be set with $VALIDATING_WEBHOOK_SERVER_CERT. |
| 217 | +--validating-webhook-server-key="/validating-certs/cert.key" |
| 218 | + A path to a server private key for ValidatingWebhook. Can be set with $VALIDATING_WEBHOOK_SERVER_KEY. |
| 219 | +--validating-webhook-ca="/validating-certs/ca.crt" |
| 220 | + A path to a ca bundle for ValidatingWebhook. Can be set with $VALIDATING_WEBHOOK_CA. |
| 221 | +--validating-webhook-client-ca=VALIDATING-WEBHOOK-CLIENT-CA ... |
| 222 | + A path to a server certificate for ValidatingWebhook. Can be set with $VALIDATING_WEBHOOK_CLIENT_CA. |
| 223 | +--validating-webhook-service-name=VALIDATING-WEBHOOK-SERVICE-NAME ... |
| 224 | + A name of a service in front of a shell-operator. Can be set with $VALIDATING_WEBHOOK_SERVICE_NAME. |
| 225 | +``` |
0 commit comments