Skip to content

Commit e77531a

Browse files
committed
Add draft proposal for status updates
1 parent a5fcfe2 commit e77531a

File tree

1 file changed

+124
-55
lines changed
  • keps/sig-api-machinery/3488-cel-admission-control

1 file changed

+124
-55
lines changed

keps/sig-api-machinery/3488-cel-admission-control/README.md

Lines changed: 124 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
- [Risks and Mitigations](#risks-and-mitigations)
5353
- [Design Details](#design-details)
5454
- [CEL Integration with Kubernetes native types](#cel-integration-with-kubernetes-native-types)
55+
- [Writing to Status](#writing-to-status)
5556
- [Versioning](#versioning)
5657
- [Policy Definition Versioning](#policy-definition-versioning)
5758
- [Configuration CRD Versioning](#configuration-crd-versioning)
@@ -301,20 +302,19 @@ for kind)
301302

302303
At a high level, the API will support:
303304

304-
- Request matching (similar to webhook Rules, NamespaceSelector,
305-
ObjectSelector)
305+
- Request matching (similar to the match rules of admission webhooks, RBAC, priority & fairness and Audit)
306306
- CEL rule evaluation (similar to both [CRD Validation
307307
Rules](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/2876-crd-validation-expression-language)
308308
and
309309
[AdmissionRequest](https://github.com/kubernetes/kubernetes/blob/2ac6a4121f5b2a94acc88d62c07d8ed1cd34ed63/staging/src/k8s.io/api/admission/v1/types.go#L40))
310-
- Automatic version conversion support (similar to webhooks MatchPolicy=Equivalent), with ability to introspect GVK of admitted resource in CEL expression.
310+
- Version conversion support (similar to webhooks MatchPolicy)
311311
- Access the old object (similar to [transition
312312
rules](https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/2876-crd-validation-expression-language#transition-rules)
313313
and oldObject in AdmissionRequest)
314314
- Configurability, as motivated above.
315315

316316
There are also lots of additional capabilities (response message formatting,
317-
severity, levels, failure policies, type safety, ...) that will be discussed
317+
failure policies, type safety, advanced matching rules, ...) that will be discussed
318318
in detail further on in this proposal.
319319

320320
We have divided this proposal into phases, all of which must be completed before
@@ -422,15 +422,15 @@ has a couple advantages:
422422
Each `ValidatingAdmissionPolicy` resource may optionally set `spec.match`
423423
to constrain the resources it validates.
424424

425-
- `spec.match` limits which resources may be matched configurations of the
426-
policy. This allows the CEL expressions to make safe assumptions. E.g. a CEL
427-
expression that is constrained to CREATES and UPDATES of resources is
428-
guaranteed the root `object` variable is never null, but a CEL expression that
429-
might need to evaluate a DELETE must handle the root `object` variable being
430-
null.
431-
- `spec.match` is used for CEL expression type checking, see the below
432-
"Type safety" section for more details.
433-
425+
- `spec.match` constraints which resources this policy can be applied to. Policy
426+
configurations each have match rules with further narrow this constraint, but
427+
cannot expand it. This allows the CEL expressions to make safe assumptions.
428+
E.g. a CEL expression that is constrained to CREATES and UPDATES of resources
429+
is guaranteed the root `object` variable is never null, but a CEL expression
430+
that might need to evaluate a DELETE must handle the root `object` variable
431+
being null.
432+
- `spec.match` guides CEL expression type checking, see the below "Type safety"
433+
section for more details.
434434

435435
Alternatives considered:
436436

@@ -463,20 +463,8 @@ If any of the above configuration CRD restrictions are violated, the errors will
463463
be reported in the status of the `ValidatingAdmissionPolicy`. If the match
464464
criteria is malformed, this unfortunately may cause the policy to fail open--
465465
without match criteria, there is no way to know what resources the policy should
466-
match.
467-
468-
TODO: (per
469-
https://github.com/kubernetes/enhancements/pull/3492#discussion_r964841045):
470-
status on API server configuration objects has been tricky to design in the
471-
past, because of the following:
472-
473-
- multiple active kube-apiservers (sometimes at identical versions, sometimes
474-
skewed by one version during upgrade)
475-
- multiple active non-kube-apiserver servers (aggregated servers)
476-
- Note: 'NonStructural' relies on the fact that the status change is a function
477-
of the resource then generation can be used
478-
(https://github.com/kubernetes/kubernetes/commit/2cfc3c69dc7c17b2711af0168f39ed7f515675c2).
479-
Can this approach be somehow extended?
466+
match. (See "Writing to Status" for more details about the structure of status
467+
and how it will be updated).
480468

481469
Note that a policy configuration CRD may be referenced by the `spec.config` of
482470
multiple `ValidatingAdmissionPolicy` resources. Each of which may apply
@@ -540,7 +528,7 @@ Matching is performed in quite a few systems across Kubernetes:
540528
| user/userGroup | Audit | phase 2? see "Secondary Authz" section |
541529
| permissions (RBAC verb) | RBAC | phase 2? see "Secondary Authz" section |
542530

543-
* WH = Admission webhooks, P&F = Priority and Fairness
531+
WH = Admission webhooks, P&F = Priority and Fairness
544532

545533
Match criteria must be declared in the `spec.match` field of policy
546534
configuration resources (see `ReplicaLimit` in the above example) and will be
@@ -588,15 +576,10 @@ type ReplicaLimit struct {
588576
}
589577
```
590578

591-
`MatchPolicy` will implicitly be `Equivalent`, and will not be configurable,
592-
but it will be possible to opt-out of the behavior by inspecting the
593-
GVK of the admitted resource in the CEL expression.
594-
595-
Note that a "accept" or "deny" decision is only reported in metrics for resources that
596-
match the criteria. If no match criteria existed, the number of "accept"
597-
occurrences would need to be much higher (the CEL expressions would need to
598-
explicitly check for all pre-conditions and accept requests that do not meet
599-
them). This would make metrics more difficult to interpret.
579+
`MatchPolicy` will work the same as for admission webhooks. It will default to
580+
`Equivalent` but may be set to `Exact`. See "Use Case: Multiple policy
581+
definitions for different versions of CRD" for an explanation of why we need
582+
`MatchPolicy`.
600583

601584
xref:
602585
https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-rules
@@ -620,10 +603,12 @@ Cons:
620603
For a policy that requires no configuration, we would prefer not to ask users
621604
create configuration CRD and configuration resource that serve no actual
622605
purpose. Instead, we will allow a `ValidatingAdmissionPolicy` to define
623-
a singleton policy:
606+
a singleton policy, the recipe is:
607+
608+
- Set a `policyType: Singleton` field
609+
- Exclude `spec.config`
624610

625-
- Has `policyType: Singleton` field
626-
- Has no `spec.config`
611+
For example:
627612

628613
```yaml
629614
apiVersion: admissionregistration.k8s.io/v1
@@ -643,10 +628,10 @@ spec:
643628
- expression: "object.spec.replicas < 100"
644629
```
645630
646-
By using a `policyType` we make it easier for a user examining the policy to
647-
observe that behaves differently from configurable policies. This is much less
648-
obvious if we infer that a policy is a singleton by the state of the other
649-
fields. It also makes validation errors reported when validating a
631+
Adding a `policyType` field makes it easier for a user examining the policy to
632+
observe that the policy is different that normal (configurable) policies. This
633+
is much less obvious if we infer that a policy is a singleton by the state of
634+
the other fields. It also makes validation errors reported when validating a
650635
`ValidatingAdmissionPolicy` much easier to communicate to the policy author.
651636

652637
#### Type safety
@@ -662,17 +647,12 @@ type-safe way we propose:
662647
- When a `ValidatingAdmissionPolicy` is created/update. Any type check errors
663648
against Kubernetes built-in types result in the create/update request
664649
failing validation with the type error.
665-
- When a configuration CRD is created/updated: The type check errors are
666-
detected by an control loop watching the CRDs with an informer in the API
667-
server, and reported in the status of the ValidatingAdmissionPolicy. The
668-
policy toggles to a "misconfigured" state where all admission requests
669-
matching and of the policy configurations of the policy fail according to
670-
the `FailureMode`.
671-
- When policy configuration resources are created/update: The type check
672-
errors are detected by an control loop watching the CRs and toggles a bit
673-
tracking that the policy configuration is "misconfigured" state where all
674-
admission requests matching the policy configuration fail according to the
675-
`FailureMode`.
650+
- When any CRD a `ValidatingAdmissionPolicy` needs for type chekcing is
651+
created/updated: The type check errors are detected by an control loop
652+
watching the CRDs with an informer in the API server, and reported in the
653+
status of the ValidatingAdmissionPolicy. The policy toggles to a
654+
"misconfigured" state where all admission requests matching and of the
655+
policy configurations of the policy fail according to the `FailureMode`.
676656

677657
Example: Typesafe access to object
678658

@@ -1243,6 +1223,95 @@ representation. For admission control, we also need CEL to be integrated with
12431223
the Kubernetes Go structs used to representative native API types, both for type
12441224
checking and for runtime data access.
12451225

1226+
### Writing to Status
1227+
1228+
This enhancement proposes using status to of `ValidatingAdmissionPolicy` to
1229+
communicate type-checking errors and any other misconfigurations such as CRD not
1230+
found errors.
1231+
1232+
As mentioned in
1233+
https://github.com/kubernetes/enhancements/pull/3492#discussion_r964841045,
1234+
status on API server configuration objects has been tricky to design in the
1235+
past, because of the following:
1236+
1237+
- multiple active kube-apiservers (sometimes at identical versions, sometimes
1238+
skewed by one version during upgrade)
1239+
- multiple active non-kube-apiserver servers (aggregated servers)
1240+
1241+
As a concrete example, The CRD `NonStructural` status field takes advantage of
1242+
the metadata generation field
1243+
(https://github.com/kubernetes/kubernetes/commit/2cfc3c69dc7c17b2711af0168f39ed7f515675c2).
1244+
1245+
We will use a similar approach. we will use `generation` numbers of resources to
1246+
determine if an apiserver is observing a state newer than the written status of
1247+
a `ValidatingAdmissionPolicy`, and will only update the status if this is true.
1248+
1249+
An apiserver controller will watch:
1250+
1251+
- `ValidatingAdmissionPolicy` resources
1252+
- All CRDs the CEL expressions need to be type checked against (Configuration
1253+
CRDs and any CRDs matched by the match criteria of the policy)
1254+
1255+
It will track the last seen `generation` of all these resources in
1256+
`ValidatingAdmissionPolicy`:
1257+
1258+
```
1259+
apiVersion: "admissionregisteration/v1alpha1"
1260+
kind: "ValidatingAdmissionPolicy"
1261+
metadata:
1262+
name: "myPolicy"
1263+
generation: 2
1264+
spec:
1265+
...
1266+
config:
1267+
apiVersion: "example.com/v1"
1268+
kind: "fooLimits"
1269+
...
1270+
status:
1271+
config:
1272+
generation: 5
1273+
matchedCustomResource:
1274+
apiVersion: "example.com/v1"
1275+
kind: "foo"
1276+
generation: 100
1277+
```
1278+
1279+
Any time any of the resources the apiserver controller is watching change, it
1280+
will check that:
1281+
1282+
- last seen ValidatingAdmissionPolicy generation is no older current
1283+
- last seen `spec.config` apiVersion/kind if different than current OR last seen
1284+
`status.config.generation` is no older than current
1285+
- last seen `status.matchedCustomResource` apiVersion/kind if different than
1286+
current OR last seen `status.matchedCustomResource.generation` is no older
1287+
than current
1288+
- At least one of the generations have increased
1289+
1290+
If all are true, then the controller has observed a forward progress of the
1291+
status and should update the status along with any conditions and errors
1292+
observed:
1293+
1294+
```
1295+
status:
1296+
...
1297+
conditions:
1298+
type: "Available" # TODO: pick an appropriate type for broken policies
1299+
status: "False"
1300+
reason: Misconfigured
1301+
message: "Validation expressions contain errors. Config custom resource definition not found."
1302+
...
1303+
validationErrors:
1304+
- expression: "object.baz > config.min"
1305+
errors:
1306+
- "illegal ..."
1307+
- "no such field ..."
1308+
configCustomResourceDefinitionErrors:
1309+
- "Config custom resource definition not found"
1310+
```
1311+
1312+
Note that write conflicts do not require a retry since the write that caused the
1313+
conflict will result in another sync once it is observed.
1314+
12461315
### Versioning
12471316

12481317
#### Policy Definition Versioning

0 commit comments

Comments
 (0)