environment.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package expressions
  2. import (
  3. "math/rand/v2"
  4. "github.com/google/cel-go/cel"
  5. "github.com/google/cel-go/common/types"
  6. "github.com/google/cel-go/common/types/ref"
  7. "github.com/google/cel-go/ext"
  8. )
  9. // BotEnvironment creates a new CEL environment, this is the set of
  10. // variables and functions that are passed into the CEL scope so that
  11. // Anubis can fail loudly and early when something is invalid instead
  12. // of blowing up at runtime.
  13. func BotEnvironment() (*cel.Env, error) {
  14. return New(
  15. // Variables exposed to CEL programs:
  16. cel.Variable("remoteAddress", cel.StringType),
  17. cel.Variable("host", cel.StringType),
  18. cel.Variable("method", cel.StringType),
  19. cel.Variable("userAgent", cel.StringType),
  20. cel.Variable("path", cel.StringType),
  21. cel.Variable("query", cel.MapType(cel.StringType, cel.StringType)),
  22. cel.Variable("headers", cel.MapType(cel.StringType, cel.StringType)),
  23. )
  24. }
  25. // NewThreshold creates a new CEL environment for threshold checking.
  26. func ThresholdEnvironment() (*cel.Env, error) {
  27. return New(
  28. cel.Variable("weight", cel.IntType),
  29. )
  30. }
  31. func New(opts ...cel.EnvOption) (*cel.Env, error) {
  32. args := []cel.EnvOption{
  33. ext.Strings(
  34. ext.StringsLocale("en_US"),
  35. ext.StringsValidateFormatCalls(true),
  36. ),
  37. // default all timestamps to UTC
  38. cel.DefaultUTCTimeZone(true),
  39. // Functions exposed to all CEL programs:
  40. cel.Function("randInt",
  41. cel.Overload("randInt_int",
  42. []*cel.Type{cel.IntType},
  43. cel.IntType,
  44. cel.UnaryBinding(func(val ref.Val) ref.Val {
  45. n, ok := val.(types.Int)
  46. if !ok {
  47. return types.ValOrErr(val, "value is not an integer, but is %T", val)
  48. }
  49. return types.Int(rand.IntN(int(n)))
  50. }),
  51. ),
  52. ),
  53. }
  54. args = append(args, opts...)
  55. return cel.NewEnv(args...)
  56. }
  57. // Compile takes CEL environment and syntax tree then emits an optimized
  58. // Program for execution.
  59. func Compile(env *cel.Env, src string) (cel.Program, error) {
  60. intermediate, iss := env.Compile(src)
  61. if iss != nil {
  62. return nil, iss.Err()
  63. }
  64. ast, iss := env.Check(intermediate)
  65. if iss != nil {
  66. return nil, iss.Err()
  67. }
  68. return env.Program(
  69. ast,
  70. cel.EvalOptions(
  71. // optimize regular expressions right now instead of on the fly
  72. cel.OptOptimize,
  73. ),
  74. )
  75. }