mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-14 13:45:06 +00:00
DRA CEL: disable runtime cost check
In DRA, the cost check is done only at validation time. At runtime, any expression that passed validation gets executed without interrupting it. The advantage is that it becomes easier to change the limit because stored expression do not suddenly fail after an up- or downgrade. The limit could even become a configuration parameter of the apiserver because that is the only place where the limit gets checked
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -130,12 +131,25 @@ func (c compiler) CompileCELExpression(expression string, envType environment.Ty
|
|||||||
return resultError("unexpected compilation error: "+err.Error(), apiservercel.ErrorTypeInternal)
|
return resultError("unexpected compilation error: "+err.Error(), apiservercel.ErrorTypeInternal)
|
||||||
}
|
}
|
||||||
prog, err := env.Program(ast,
|
prog, err := env.Program(ast,
|
||||||
// cel.CostLimit is also set to the VAP PerCallLimit as part of
|
// The Kubernetes CEL base environment sets the VAP cost limit.
|
||||||
// the base environment.
|
|
||||||
//
|
//
|
||||||
// This call here should override that. In practice it shouldn't
|
// In DRA, the cost check is done only at validation time. At
|
||||||
// matter because the limits are the same.
|
// runtime, any expression that passed validation gets executed
|
||||||
cel.CostLimit(resourceapi.CELSelectorExpressionMaxCost),
|
// without interrupting it. The advantage is that it becomes
|
||||||
|
// easier to change the limit because stored expression do not
|
||||||
|
// suddenly fail after an up- or downgrade. The limit could
|
||||||
|
// even become a configuration parameter of the apiserver
|
||||||
|
// because that is the only place where the limit gets checked
|
||||||
|
//
|
||||||
|
// We cannot unset the cost limit
|
||||||
|
// (https://github.com/kubernetes/kubernetes/blob/9568a2ac145cf9be930e3da835f86c1e61f7f7c1/vendor/github.com/google/cel-go/cel/options.go#L512-L518). But
|
||||||
|
// we can set a high value that then never triggers
|
||||||
|
// (https://github.com/kubernetes/kubernetes/blob/9568a2ac145cf9be930e3da835f86c1e61f7f7c1/vendor/github.com/google/cel-go/interpreter/runtimecost.go#L104-L106).
|
||||||
|
//
|
||||||
|
// Even better would be to enable cost tracking only during
|
||||||
|
// validation, but for that k8s.io/apiserver/pkg/cel/environment would
|
||||||
|
// have to be changed to not set the limit.
|
||||||
|
cel.CostLimit(math.MaxInt64),
|
||||||
cel.InterruptCheckFrequency(celconfig.CheckFrequency),
|
cel.InterruptCheckFrequency(celconfig.CheckFrequency),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -227,10 +227,9 @@ device.attributes["dra.example.com"]["version"].isGreaterThan(semver("0.0.1"))
|
|||||||
}
|
}
|
||||||
return attributes
|
return attributes
|
||||||
}(),
|
}(),
|
||||||
expression: `device.attributes["dra.example.com"].map(s, s.lowerAscii()).map(s, s.size()).sum() == 0`,
|
expression: `device.attributes["dra.example.com"].map(s, s.lowerAscii()).map(s, s.size()).sum() == 0`,
|
||||||
driver: "dra.example.com",
|
driver: "dra.example.com",
|
||||||
expectMatchError: "actual cost limit exceeded",
|
expectCost: 18446744073709551615, // Exceeds limit!
|
||||||
expectCost: 18446744073709551615, // Exceeds limit!
|
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
|
Reference in New Issue
Block a user