Skip to content

Commit 6bfa6de

Browse files
committed
Clean up message options
1 parent e5ee4a2 commit 6bfa6de

File tree

1 file changed

+81
-20
lines changed
  • keps/sig-api-machinery/3488-cel-admission-control

1 file changed

+81
-20
lines changed

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

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -969,29 +969,40 @@ Without any additional support, the only possible approach is:
969969
```
970970

971971
But if we were to offer a way for some validations to short-circuit validation
972-
execution, this would be cleaner. E.g.:
972+
execution, this could be simpler. E.g.:
973973

974974
```yaml
975975
validations:
976976
- expression: "<CEL match expression>"
977-
onSuccess: HaltValidation
978-
- expression: "<actual validation expression 1>"
979-
- expression: "<actual validation expression 2>"
977+
failureTreatment: NoMatch # TODO: What's the least bad way to express this?
978+
- expression: "<normal validation expression 1>"
979+
- expression: "<normal validation expression 2>"
980980
```
981981

982982
The other use for short-circuiting is to skip any other validations, this can be
983-
used in a security context to prevent messages from exfiltrating data, or more
984-
generally to minimize noise where subsequent validation messages are of low
985-
value if a particular validation fails.
983+
used in a security context (if authz check fails, don't show user any other
984+
info), or more generally to minimize noise where subsequent validation messages
985+
are of low value if a particular validation fails.
986986

987987
```yaml
988988
validations:
989989
- expression: "<CEL precondition check>"
990-
onFail: HaltValidation
991-
- expression: "<CEL post-condition check>"
992-
- expression: "<CEL post-condition check>"
990+
failureTreatment: IgnoreOtherValidationFailures
991+
- expression: "..."
992+
- expression: "..."
993993
```
994994

995+
`failureTreatment` would support:
996+
997+
- `NoMatch` - The resource is considered "not matched" by this policy check and
998+
is allowed to be admitted (at least by this policy) regardless of the outcome
999+
of other validations.
1000+
- `Enforce` - Apply the enforcement of this validation.
1001+
- `IgnoreOtherValidationFailures` - Only this policy failure is enforced. Any
1002+
other validation failures are ignored. If multiple validations have this
1003+
`failureTreatment` the first in the list to failure is shown and all others
1004+
are ignored.
1005+
9951006
*Special case: apiGroup + resource + operation matching*
9961007

9971008
For admission webhooks, at least one `spec.rules` must be declared to state
@@ -1091,19 +1102,61 @@ when validations fail.
10911102

10921103
<<[UNRESOLVED jpbetz, DangerOnTheRanger ]>>
10931104

1094-
Is it reasonable to also use CEL expressions to format messages? CEL is strict
1095-
about types, so things like `object.int1 + ' is less than ' + object.int2`, must be
1096-
expressed as `string(object.int1) + ' is less than ' + string(object.int2)`.
1105+
Decide on message formatting.
1106+
1107+
Alternative: offer a CEL expression
1108+
1109+
```yaml
1110+
- expression: "..."
1111+
messageExpression: "string(object.int1) + ' is less than ' + string(object.int2)"
1112+
```
1113+
1114+
Cons:
1115+
1116+
- CEL requires explicit casts to string
1117+
- Plain string message support is a bit messy. Options:
1118+
- Use CEL always: `"'this is a simple message'"`
1119+
- Offer both plain string (`message`) and CEL (`messageExpression`)
10971120

1098-
Alternative:
1121+
Alternative: Inline CEL expressions
10991122

11001123
Single `message` field but it supports templating, e.g.:
11011124

11021125
```
11031126
"{{object.int1}} is less than {{object.int2}}"
11041127
```
11051128

1106-
Where the templating uses CEL expressions.
1129+
Cons:
1130+
1131+
- Must defining escaping rules in string for including `{{` or `}}` as a literal
1132+
- CEL expressions must be properly escaped
1133+
1134+
Alternative: Inline JSON path
1135+
1136+
```
1137+
"{{.object.int1}} is less than {{.object.int2}}"
1138+
```
1139+
1140+
Cons:
1141+
1142+
- (Same as above "Inline CEL expressions")
1143+
- Author must switch between using CEL and JSON Path in adjacent fields
1144+
- JSON Path is less expressive than CEL (both a pro and a con)
1145+
1146+
Alternative: CEL expressions, separate args from format string
1147+
1148+
```yaml
1149+
- expression: "..."
1150+
message: "{1} is less than {2}"
1151+
messageArgs: ["object.int1", "object.int2"]
1152+
```
1153+
1154+
Note "%s is less than %s" is also viable, but CEL can always preformat and emit
1155+
a string for cases where developer needs more control.
1156+
1157+
Cons:
1158+
1159+
- Slightly more verbose format (but avoid all the escaping problems)
11071160

11081161
<<[/UNRESOLVED]>>
11091162

@@ -1118,8 +1171,12 @@ High level proposal:
11181171

11191172
- Each policy may set a `denyReason` and/or `denyCode`
11201173
- Each validation may define a message:
1121-
- `message` for plain strings
1122-
- `messageExpression` for a CEL expression that evaluates to a string
1174+
- `message` - may contain `{1}` formatted args that are supplied by
1175+
`meesageArgs: [<cel expression>, <cel expressiion>, ...]`
1176+
- If `meesage` is absent, `expression` and `name` will be included in the
1177+
failure message
1178+
- If any of the arg CEL expressions fail: `expression` and `name` will be
1179+
included in the failure message plus the arg evaluation failure
11231180
- allow/deny, warnings, audit annotations will be collectively referred to as
11241181
`enforcement`, which will have the following levels:
11251182
- `Deny`,
@@ -1129,7 +1186,7 @@ High level proposal:
11291186
enforcement is `Audit` the name can be used as the audit annotation key.
11301187
- Policy configurations set enforcement options
11311188

1132-
Example:
1189+
Example policy definition:
11331190

11341191
```yaml
11351192
# Policy definition
@@ -1146,15 +1203,19 @@ spec:
11461203
validations:
11471204
- expression: "self.name.startsWith('xyz-')"
11481205
name: name-prefix
1149-
messageExpression: "self.name + ' must start with \"xyz-\"'"
1206+
message: "{1} must start with 'xyz-'"
1207+
messageArgs: ["self.name"]
11501208
- expression: "self.name.contains('bad')"
11511209
name: bad-name
11521210
message: "name contains 'bad' which is discouraged due to ..."
11531211
- expression: "self.name.contains('suspicious')"
11541212
name: suspicious-name
1155-
messageExpression: "self.name + ' contains \"suspicious\"'"
1213+
messageExpression: "{1} contains 'suspicious'"
1214+
messageArgs: ["self.name"]
11561215
```
11571216

1217+
corresponding policy configuration:
1218+
11581219
```yaml
11591220
kind: XyzConfig
11601221
...

0 commit comments

Comments
 (0)