@@ -1316,25 +1316,29 @@ Note that `matchConditions` and `validations` look similar, but `matchConditions
1316
1316
1317
1317
# ### CEL Expression Composition
1318
1318
1319
+ Expression Composition is a technique to define a set of variables each from
1320
+ a given expression and allow validation expressions to refer the variables.
1321
+
1319
1322
# #### Use Cases
1320
1323
1324
+ # ##### Reusing/memorizing an expensive computation and lazy evaluation
1325
+
1326
+ For a CEL expression that takes a significant time to evaluate, especially
1327
+ these that cost O(N^2) time or worse, it would be nice to only run it once
1328
+ and only when necessary. If multiple validation expressions used the same
1329
+ expression, that expression could be refactored out into a variable.
1330
+ Because of the evaluation of a composited variable is lazy, if the value of some variable
1331
+ does not affect the result of an expression due to boolean short-circuit evaluation,
1332
+ the variable can be omitted and does not incur runtime cost.
1333
+
1321
1334
# ##### Code re-use for complicated expressions
1322
1335
1323
1336
A CEL expression may not be computationally expensive, but could still be
1324
1337
intricate enough that copy-pasting could prove to be a bad decision later on
1325
- in time. With the addition of the `messageExpression` field, more copy-pasting
1326
- is expected as well. If a sufficiently complex expression ended up copy-pasted everywhere,
1327
- and then needs to be updated somehow, it will need that update in every place
1328
- it was copy-pasted. A variable, on the other hand, will only need to be updated
1329
- in one place.
1330
-
1331
- # ##### Reusing/memoizing an expensive computation
1332
-
1333
- For a CEL expression that runs in O(n^2) time or worse (or otherwise
1334
- takes a significant amount of time to execute), it would be nice to only run
1335
- it when necessary. For instance, if multiple validation expressions used the
1336
- same expensive expression, that expression could be refactored out into a
1337
- variable.
1338
+ in time. For example, a sub-expression is likely used both in the validation and
1339
+ to format `messageExpression`. If a sufficiently complex expression ended up
1340
+ copy-pasted everywhere, and then needs to be updated somehow, it will need that update in every place
1341
+ it was copy-pasted. A variable, on the other hand, will only need to be updated in one place.
1338
1342
1339
1343
# #### Variables
1340
1344
@@ -1343,18 +1347,17 @@ assignment. This can result in redundant code to traverse maps/arrays or
1343
1347
dereference particular fields.
1344
1348
1345
1349
We can support this in much the same way as cel-policy-template `terms`. These
1346
- can be lazily evaluated while the validation expressions are evaluated
1347
- (cel-policy-template does this).
1350
+ can be lazily evaluated when they are resolved during the evaluation of
1351
+ the main expression (cel-policy-template does this).
1348
1352
1349
- A policy can include an additional `variables` section. This is an array
1353
+ The policy spec now has an additional `variables` section. This is an array
1350
1354
containing one or more `name` and `expression` pairs, which can be used/re-used by
1351
1355
the policy's validation expressions. These results are memoized on a
1352
1356
per-validation basis, so if multiple expressions use the same spec variables,
1353
1357
the expression that calculates the variable's value will only run once.
1354
1358
1355
1359
The variables can be accessed as members of `variables`, which is an object
1356
- that is exposed to CEL expressions (both validation expressions as well as
1357
- other variables).
1360
+ that is exposed to CEL expressions (both validation expressions and other variables).
1358
1361
1359
1362
For example :
1360
1363
@@ -1369,16 +1372,16 @@ For example:
1369
1372
- expression: "variables.itemMetadataNames.exists(name, name == 'required')"
1370
1373
` ` `
1371
1374
1372
- Variable names must be valid CEL names. What constitutes a
1373
- valid CEL name can be found at CEL's [language definition](https://github.com/google/cel-spec/blob/master/doc/langdef.md#syntax) under `IDENT`.
1374
- This validity is checked at write time .
1375
+ Variable names must be valid CEL names and must be unique among all variables . What constitutes a
1376
+ valid CEL name can be found at CEL[language definition](https://github.com/google/cel-spec/blob/master/doc/langdef.md#syntax)
1377
+ under `IDENT`. This validity is checked when the policy is being created or updated .
1375
1378
1376
1379
For per-policy runtime cost limit purposes, variables count towards the runtime cost limit
1377
1380
once per policy. The cost of each variable is computed when it is first evaluated in an
1378
1381
expression, mirroring how the cost limit would be calculated if the variable's
1379
1382
expression was embedded verbatim. If the runtime cost limit is exceeded in the
1380
1383
process, then evaluation halts. No individual variable or expression will be listed as the
1381
- cause in the resulting message. Whether or not the request actually fails depends on the failure policy,
1384
+ cause in the resulting message. Whether the request actually fails depends on the failure policy,
1382
1385
however. For subsequent uses, inclusion of the variable has zero effect on the runtime
1383
1386
cost limit. If the variable evaluates to an array or some other iterable, and some expression
1384
1387
iterates on it, that of course contributes to the cost limit, but simply including the variable does
@@ -1387,16 +1390,13 @@ not add the underlying expression's cost again.
1387
1390
Variables are also subject to the per-expression runtime cost limit. Exceeding the per-expression
1388
1391
runtime cost limit is always attributed to the variable, unlike the per-policy limit.
1389
1392
1390
- Variables can only reference other variables that
1391
- have been previously defined in the `variables` section, so circular references
1392
- are not allowed.
1393
+ Variables can only reference other variables that have been previously defined in the `variables` section.
1394
+ This will have a side effect of making the order of the variable definitions matter but prevents circular reference.
1393
1395
1394
- If an error ocurrs during variable evaluation, then the expression
1395
- that caused it to be evaluated (since variable are always
1396
- lazily-evaluated) also finishes with an error. Evaluation for that
1397
- variable is not attempted again during the same validation; if any other
1398
- expressions attempt to evaluate a variable that already failed an evaluation
1399
- attempt, they will also be considered to have failed.
1396
+ Both the result and potential error of a variable evaluation are memorized.
1397
+ If an error occurs during variable evaluation, then every validation expression
1398
+ that caused it to be evaluated (since variable are always lazily-evaluated)
1399
+ also finishes with an error, and the variable evaluation will not retry.
1400
1400
1401
1401
# ### Secondary Authz
1402
1402
@@ -1658,8 +1658,11 @@ Goals:
1658
1658
- Parity with admission webhook metrics
1659
1659
- Should include counter of deny, warn and audit violations
1660
1660
- Label by {policy, policy binding, validation expression} identifiers
1661
- - Counters for number of policy defintions and policy bindings in cluster
1661
+ - Counters for number of policy definitions and policy bindings in cluster
1662
1662
- Label by state (active vs. error), enforcement action (deny, warn)
1663
+ - Counters for Variable Composition
1664
+ - Should include counter of variable resolutions to measure time saved.
1665
+ - Label by policy identifier
1663
1666
1664
1667
Granularity :
1665
1668
0 commit comments