mirror of
https://github.com/TecharoHQ/anubis.git
synced 2025-08-03 17:59:24 -04:00

This lets Anubis dynamically react to system load in order to increase and decrease the required level of scrutiny. High load? More scrutiny required. Low load? Less scrutiny required.
86 lines
1.8 KiB
Go
86 lines
1.8 KiB
Go
package policy
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"github.com/TecharoHQ/anubis/internal"
|
|
"github.com/TecharoHQ/anubis/lib/policy/config"
|
|
"github.com/TecharoHQ/anubis/lib/policy/expressions"
|
|
"github.com/google/cel-go/cel"
|
|
"github.com/google/cel-go/common/types"
|
|
)
|
|
|
|
type CELChecker struct {
|
|
program cel.Program
|
|
src string
|
|
}
|
|
|
|
func NewCELChecker(cfg *config.ExpressionOrList) (*CELChecker, error) {
|
|
env, err := expressions.BotEnvironment()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
program, err := expressions.Compile(env, cfg.String())
|
|
if err != nil {
|
|
return nil, fmt.Errorf("can't compile CEL program: %w", err)
|
|
}
|
|
|
|
return &CELChecker{
|
|
src: cfg.String(),
|
|
program: program,
|
|
}, nil
|
|
}
|
|
|
|
func (cc *CELChecker) Hash() string {
|
|
return internal.FastHash(cc.src)
|
|
}
|
|
|
|
func (cc *CELChecker) Check(r *http.Request) (bool, error) {
|
|
result, _, err := cc.program.ContextEval(r.Context(), &CELRequest{r})
|
|
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
if val, ok := result.(types.Bool); ok {
|
|
return bool(val), nil
|
|
}
|
|
|
|
return false, nil
|
|
}
|
|
|
|
type CELRequest struct {
|
|
*http.Request
|
|
}
|
|
|
|
func (cr *CELRequest) Parent() cel.Activation { return nil }
|
|
|
|
func (cr *CELRequest) ResolveName(name string) (any, bool) {
|
|
switch name {
|
|
case "remoteAddress":
|
|
return cr.Header.Get("X-Real-Ip"), true
|
|
case "host":
|
|
return cr.Host, true
|
|
case "method":
|
|
return cr.Method, true
|
|
case "userAgent":
|
|
return cr.UserAgent(), true
|
|
case "path":
|
|
return cr.URL.Path, true
|
|
case "query":
|
|
return expressions.URLValues{Values: cr.URL.Query()}, true
|
|
case "headers":
|
|
return expressions.HTTPHeaders{Header: cr.Header}, true
|
|
case "load_1m":
|
|
return expressions.Load1(), true
|
|
case "load_5m":
|
|
return expressions.Load5(), true
|
|
case "load_15m":
|
|
return expressions.Load15(), true
|
|
default:
|
|
return nil, false
|
|
}
|
|
}
|