feat(config): custom weight thresholds via CEL (#688)

* feat(config): add Thresholds to the top level config file

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(config): make String() on ExpressionOrList join the component expressions

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(config): ensure unparseable json fails

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(config): if no thresholds are set, use the default thresholds

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(policy): half implement thresholds

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(policy): continue wiring things up

Signed-off-by: Xe Iaso <me@xeiaso.net>

* feat(lib): wire up thresholds

Signed-off-by: Xe Iaso <me@xeiaso.net>

* test(lib): handle behavior from legacy configurations

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: document thresholds

Signed-off-by: Xe Iaso <me@xeiaso.net>

* docs: update CHANGELOG, refer to threshold configuration

Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix(lib): fix build

Signed-off-by: Xe Iaso <me@xeiaso.net>

* chore(lib): fix U1000

Signed-off-by: Xe Iaso <me@xeiaso.net>

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
Signed-off-by: Jason Cameron <git@jasoncameron.dev>
Co-authored-by: Jason Cameron <git@jasoncameron.dev>
This commit is contained in:
Xe Iaso 2025-06-18 16:58:31 -04:00 committed by GitHub
parent 1d5fa49eb0
commit 226cf36bf7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 683 additions and 305 deletions

View file

@ -9,20 +9,12 @@ import (
"github.com/google/cel-go/ext"
)
// NewEnvironment creates a new CEL environment, this is the set of
// BotEnvironment creates a new CEL environment, this is the set of
// variables and functions that are passed into the CEL scope so that
// Anubis can fail loudly and early when something is invalid instead
// of blowing up at runtime.
func NewEnvironment() (*cel.Env, error) {
return cel.NewEnv(
ext.Strings(
ext.StringsLocale("en_US"),
ext.StringsValidateFormatCalls(true),
),
// default all timestamps to UTC
cel.DefaultUTCTimeZone(true),
func BotEnvironment() (*cel.Env, error) {
return New(
// Variables exposed to CEL programs:
cel.Variable("remoteAddress", cel.StringType),
cel.Variable("host", cel.StringType),
@ -31,8 +23,27 @@ func NewEnvironment() (*cel.Env, error) {
cel.Variable("path", cel.StringType),
cel.Variable("query", cel.MapType(cel.StringType, cel.StringType)),
cel.Variable("headers", cel.MapType(cel.StringType, cel.StringType)),
)
}
// Functions exposed to CEL programs:
// NewThreshold creates a new CEL environment for threshold checking.
func ThresholdEnvironment() (*cel.Env, error) {
return New(
cel.Variable("weight", cel.IntType),
)
}
func New(opts ...cel.EnvOption) (*cel.Env, error) {
args := []cel.EnvOption{
ext.Strings(
ext.StringsLocale("en_US"),
ext.StringsValidateFormatCalls(true),
),
// default all timestamps to UTC
cel.DefaultUTCTimeZone(true),
// Functions exposed to all CEL programs:
cel.Function("randInt",
cel.Overload("randInt_int",
[]*cel.Type{cel.IntType},
@ -47,12 +58,25 @@ func NewEnvironment() (*cel.Env, error) {
}),
),
),
)
}
args = append(args, opts...)
return cel.NewEnv(args...)
}
// Compile takes CEL environment and syntax tree then emits an optimized
// Program for execution.
func Compile(env *cel.Env, ast *cel.Ast) (cel.Program, error) {
func Compile(env *cel.Env, src string) (cel.Program, error) {
intermediate, iss := env.Compile(src)
if iss != nil {
return nil, iss.Err()
}
ast, iss := env.Check(intermediate)
if iss != nil {
return nil, iss.Err()
}
return env.Program(
ast,
cel.EvalOptions(