@@ -969,29 +969,40 @@ Without any additional support, the only possible approach is:
969
969
` ` `
970
970
971
971
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. :
973
973
974
974
` ` ` yaml
975
975
validations:
976
976
- 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>"
980
980
` ` `
981
981
982
982
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.
986
986
987
987
` ` ` yaml
988
988
validations:
989
989
- 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: "... "
993
993
` ` `
994
994
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
+
995
1006
*Special case: apiGroup + resource + operation matching*
996
1007
997
1008
For admission webhooks, at least one `spec.rules` must be declared to state
@@ -1091,19 +1102,61 @@ when validations fail.
1091
1102
1092
1103
<<[UNRESOLVED jpbetz, DangerOnTheRanger ]>>
1093
1104
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`)
1097
1120
1098
- Alternative :
1121
+ Alternative : Inline CEL expressions
1099
1122
1100
1123
Single `message` field but it supports templating, e.g. :
1101
1124
1102
1125
` ` `
1103
1126
"{{object.int1}} is less than {{object.int2}}"
1104
1127
` ` `
1105
1128
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)
1107
1160
1108
1161
<<[/UNRESOLVED]>>
1109
1162
@@ -1118,8 +1171,12 @@ High level proposal:
1118
1171
1119
1172
- Each policy may set a `denyReason` and/or `denyCode`
1120
1173
- 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
1123
1180
- allow/deny, warnings, audit annotations will be collectively referred to as
1124
1181
`enforcement`, which will have the following levels :
1125
1182
- ` Deny` ,
@@ -1129,7 +1186,7 @@ High level proposal:
1129
1186
enforcement is `Audit` the name can be used as the audit annotation key.
1130
1187
- Policy configurations set enforcement options
1131
1188
1132
- Example :
1189
+ Example policy definition :
1133
1190
1134
1191
` ` ` yaml
1135
1192
# Policy definition
@@ -1146,15 +1203,19 @@ spec:
1146
1203
validations:
1147
1204
- expression: "self.name.startsWith('xyz-')"
1148
1205
name: name-prefix
1149
- messageExpression: "self.name + ' must start with \" xyz-\" '"
1206
+ message: "{1} must start with 'xyz-'"
1207
+ messageArgs: ["self.name"]
1150
1208
- expression: "self.name.contains('bad')"
1151
1209
name: bad-name
1152
1210
message: "name contains 'bad' which is discouraged due to ..."
1153
1211
- expression: "self.name.contains('suspicious')"
1154
1212
name: suspicious-name
1155
- messageExpression: "self.name + ' contains \" suspicious\" '"
1213
+ messageExpression: "{1} contains 'suspicious'"
1214
+ messageArgs: ["self.name"]
1156
1215
` ` `
1157
1216
1217
+ corresponding policy configuration :
1218
+
1158
1219
` ` ` yaml
1159
1220
kind: XyzConfig
1160
1221
...
0 commit comments