52
52
- [ Risks and Mitigations] ( #risks-and-mitigations )
53
53
- [ Design Details] ( #design-details )
54
54
- [ CEL Integration with Kubernetes native types] ( #cel-integration-with-kubernetes-native-types )
55
+ - [ Writing to Status] ( #writing-to-status )
55
56
- [ Versioning] ( #versioning )
56
57
- [ Policy Definition Versioning] ( #policy-definition-versioning )
57
58
- [ Configuration CRD Versioning] ( #configuration-crd-versioning )
@@ -301,20 +302,19 @@ for kind)
301
302
302
303
At a high level, the API will support:
303
304
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)
306
306
- CEL rule evaluation (similar to both [ CRD Validation
307
307
Rules] ( https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/2876-crd-validation-expression-language )
308
308
and
309
309
[ 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)
311
311
- Access the old object (similar to [ transition
312
312
rules] ( https://github.com/kubernetes/enhancements/tree/master/keps/sig-api-machinery/2876-crd-validation-expression-language#transition-rules )
313
313
and oldObject in AdmissionRequest)
314
314
- Configurability, as motivated above.
315
315
316
316
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
318
318
in detail further on in this proposal.
319
319
320
320
We have divided this proposal into phases, all of which must be completed before
@@ -422,15 +422,15 @@ has a couple advantages:
422
422
Each ` ValidatingAdmissionPolicy` resource may optionally set `spec.match`
423
423
to constrain the resources it validates.
424
424
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.
434
434
435
435
Alternatives considered :
436
436
@@ -463,20 +463,8 @@ If any of the above configuration CRD restrictions are violated, the errors will
463
463
be reported in the status of the `ValidatingAdmissionPolicy`. If the match
464
464
criteria is malformed, this unfortunately may cause the policy to fail open--
465
465
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).
480
468
481
469
Note that a policy configuration CRD may be referenced by the `spec.config` of
482
470
multiple `ValidatingAdmissionPolicy` resources. Each of which may apply
@@ -540,7 +528,7 @@ Matching is performed in quite a few systems across Kubernetes:
540
528
| user/userGroup | Audit | phase 2? see "Secondary Authz" section |
541
529
| permissions (RBAC verb) | RBAC | phase 2? see "Secondary Authz" section |
542
530
543
- * WH = Admission webhooks, P&F = Priority and Fairness
531
+ WH = Admission webhooks, P&F = Priority and Fairness
544
532
545
533
Match criteria must be declared in the `spec.match` field of policy
546
534
configuration resources (see `ReplicaLimit` in the above example) and will be
@@ -588,15 +576,10 @@ type ReplicaLimit struct {
588
576
}
589
577
```
590
578
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 ` .
600
583
601
584
xref:
602
585
https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/#matching-requests-rules
@@ -620,10 +603,12 @@ Cons:
620
603
For a policy that requires no configuration, we would prefer not to ask users
621
604
create configuration CRD and configuration resource that serve no actual
622
605
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 `
624
610
625
- - Has ` policyType: Singleton ` field
626
- - Has no ` spec.config `
611
+ For example:
627
612
628
613
``` yaml
629
614
apiVersion : admissionregistration.k8s.io/v1
@@ -643,10 +628,10 @@ spec:
643
628
- expression : " object.spec.replicas < 100"
644
629
` ` `
645
630
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
650
635
` ValidatingAdmissionPolicy` much easier to communicate to the policy author.
651
636
652
637
# ### Type safety
@@ -662,17 +647,12 @@ type-safe way we propose:
662
647
- When a `ValidatingAdmissionPolicy` is created/update. Any type check errors
663
648
against Kubernetes built-in types result in the create/update request
664
649
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`.
676
656
677
657
Example : Typesafe access to object
678
658
@@ -1243,6 +1223,95 @@ representation. For admission control, we also need CEL to be integrated with
1243
1223
the Kubernetes Go structs used to representative native API types, both for type
1244
1224
checking and for runtime data access.
1245
1225
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
+
1246
1315
# ## Versioning
1247
1316
1248
1317
# ### Policy Definition Versioning
0 commit comments