nuke/lib/policy/celchecker.go
Xe Iaso f032d5d0ac
feat: writing logs to the filesystem with rotation support (#1299)
* refactor: move lib/policy/config to lib/config

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

* refactor: don't set global loggers anymore

Ref #864

You were right @kotx, it is a bad idea to set the global logger
instance.

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

* feat(config): add log sink support

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

* chore: update spelling

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

* chore(test): go mod tidy

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

* chore: update spelling

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

* docs(admin/policies): add logging block documentation

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

* docs: update CHANGELOG

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

* fix(cmd/anubis): revert this change, it's meant to be its own PR

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

* chore: go mod tidy

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

* test: add file logging smoke test

Assisted-by: GLM 4.6 via Claude Code
Signed-off-by: Xe Iaso <me@xeiaso.net>

* fix: don't expose the old log file time format string

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

---------

Signed-off-by: Xe Iaso <me@xeiaso.net>
2025-11-21 11:46:00 -05:00

87 lines
1.8 KiB
Go

package policy
import (
"fmt"
"net/http"
"github.com/TecharoHQ/anubis/internal"
"github.com/TecharoHQ/anubis/lib/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 "contentLength":
return cr.ContentLength, 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
}
}