crowdsec/pkg/exprhelpers/expr_lib.go
Thibault "bui" Koechlin 8cca4346a5
Application Security Engine Support (#2273)
Add a new datasource that:
- Receives HTTP requests from remediation components
- Apply rules on them to determine whether they are malicious or not
- Rules can be evaluated in-band (the remediation component will block the request directly) or out-band (the RC will let the request through, but crowdsec can still process the rule matches with scenarios)

The PR also adds support for 2 new hub items:
- appsec-configs: Configure the Application Security Engine (which rules to load, in which phase)
- appsec-rules: a rule that is added in the Application Security Engine (can use either our own format, or seclang)

---------

Co-authored-by: alteredCoder <kevin@crowdsec.net>
Co-authored-by: Sebastien Blot <sebastien@crowdsec.net>
Co-authored-by: mmetc <92726601+mmetc@users.noreply.github.com>
Co-authored-by: Marco Mariani <marco@crowdsec.net>
2023-12-07 12:21:04 +01:00

448 lines
8 KiB
Go

package exprhelpers
import (
"time"
"github.com/crowdsecurity/crowdsec/pkg/cticlient"
)
type exprCustomFunc struct {
name string
function func(params ...any) (any, error)
signature []interface{}
}
var exprFuncs = []exprCustomFunc{
{
name: "CrowdsecCTI",
function: CrowdsecCTI,
signature: []interface{}{
new(func(string) (*cticlient.SmokeItem, error)),
},
},
{
name: "Flatten",
function: Flatten,
signature: []interface{}{},
},
{
name: "Distinct",
function: Distinct,
signature: []interface{}{},
},
{
name: "FlattenDistinct",
function: FlattenDistinct,
signature: []interface{}{},
},
{
name: "Distance",
function: Distance,
signature: []interface{}{
new(func(string, string, string, string) (float64, error)),
},
},
{
name: "GetFromStash",
function: GetFromStash,
signature: []interface{}{
new(func(string, string) (string, error)),
},
},
{
name: "Atof",
function: Atof,
signature: []interface{}{
new(func(string) float64),
},
},
{
name: "JsonExtract",
function: JsonExtract,
signature: []interface{}{
new(func(string, string) string),
},
},
{
name: "JsonExtractUnescape",
function: JsonExtractUnescape,
signature: []interface{}{
new(func(string, ...string) string),
},
},
{
name: "JsonExtractLib",
function: JsonExtractLib,
signature: []interface{}{
new(func(string, ...string) string),
},
},
{
name: "JsonExtractSlice",
function: JsonExtractSlice,
signature: []interface{}{
new(func(string, string) []interface{}),
},
},
{
name: "JsonExtractObject",
function: JsonExtractObject,
signature: []interface{}{
new(func(string, string) map[string]interface{}),
},
},
{
name: "ToJsonString",
function: ToJson,
signature: []interface{}{
new(func(interface{}) string),
},
},
{
name: "File",
function: File,
signature: []interface{}{
new(func(string) []string),
},
},
{
name: "RegexpInFile",
function: RegexpInFile,
signature: []interface{}{
new(func(string, string) bool),
},
},
{
name: "Upper",
function: Upper,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "Lower",
function: Lower,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "IpInRange",
function: IpInRange,
signature: []interface{}{
new(func(string, string) bool),
},
},
{
name: "TimeNow",
function: TimeNow,
signature: []interface{}{
new(func() string),
},
},
{
name: "ParseUri",
function: ParseUri,
signature: []interface{}{
new(func(string) map[string][]string),
},
},
{
name: "PathUnescape",
function: PathUnescape,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "QueryUnescape",
function: QueryUnescape,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "PathEscape",
function: PathEscape,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "QueryEscape",
function: QueryEscape,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "XMLGetAttributeValue",
function: XMLGetAttributeValue,
signature: []interface{}{
new(func(string, string, string) string),
},
},
{
name: "XMLGetNodeValue",
function: XMLGetNodeValue,
signature: []interface{}{
new(func(string, string) string),
},
},
{
name: "IpToRange",
function: IpToRange,
signature: []interface{}{
new(func(string, string) string),
},
},
{
name: "IsIPV6",
function: IsIPV6,
signature: []interface{}{
new(func(string) bool),
},
},
{
name: "IsIPV4",
function: IsIPV4,
signature: []interface{}{
new(func(string) bool),
},
},
{
name: "IsIP",
function: IsIP,
signature: []interface{}{
new(func(string) bool),
},
},
{
name: "LookupHost",
function: LookupHost,
signature: []interface{}{
new(func(string) []string),
},
},
{
name: "GetDecisionsCount",
function: GetDecisionsCount,
signature: []interface{}{
new(func(string) int),
},
},
{
name: "GetDecisionsSinceCount",
function: GetDecisionsSinceCount,
signature: []interface{}{
new(func(string, string) int),
},
},
{
name: "Sprintf",
function: Sprintf,
signature: []interface{}{
new(func(string, ...interface{}) string),
},
},
{
name: "ParseUnix",
function: ParseUnix,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "SetInStash", //FIXME: signature will probably blow everything up
function: SetInStash,
signature: []interface{}{
new(func(string, string, string, *time.Duration) error),
},
},
{
name: "Fields",
function: Fields,
signature: []interface{}{
new(func(string) []string),
},
},
{
name: "Index",
function: Index,
signature: []interface{}{
new(func(string, string) int),
},
},
{
name: "IndexAny",
function: IndexAny,
signature: []interface{}{
new(func(string, string) int),
},
},
{
name: "Join",
function: Join,
signature: []interface{}{
new(func([]string, string) string),
},
},
{
name: "Split",
function: Split,
signature: []interface{}{
new(func(string, string) []string),
},
},
{
name: "SplitAfter",
function: SplitAfter,
signature: []interface{}{
new(func(string, string) []string),
},
},
{
name: "SplitAfterN",
function: SplitAfterN,
signature: []interface{}{
new(func(string, string, int) []string),
},
},
{
name: "SplitN",
function: SplitN,
signature: []interface{}{
new(func(string, string, int) []string),
},
},
{
name: "Replace",
function: Replace,
signature: []interface{}{
new(func(string, string, string, int) string),
},
},
{
name: "ReplaceAll",
function: ReplaceAll,
signature: []interface{}{
new(func(string, string, string) string),
},
},
{
name: "Trim",
function: Trim,
signature: []interface{}{
new(func(string, string) string),
},
},
{
name: "TrimLeft",
function: TrimLeft,
signature: []interface{}{
new(func(string, string) string),
},
},
{
name: "TrimRight",
function: TrimRight,
signature: []interface{}{
new(func(string, string) string),
},
},
{
name: "TrimSpace",
function: TrimSpace,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "TrimPrefix",
function: TrimPrefix,
signature: []interface{}{
new(func(string, string) string),
},
},
{
name: "TrimSuffix",
function: TrimSuffix,
signature: []interface{}{
new(func(string, string) string),
},
},
{
name: "Get",
function: Get,
signature: []interface{}{
new(func([]string, int) string),
},
},
{
name: "ToString",
function: ToString,
signature: []interface{}{
new(func(interface{}) string),
},
},
{
name: "Match",
function: Match,
signature: []interface{}{
new(func(string, string) bool),
},
},
{
name: "KeyExists",
function: KeyExists,
signature: []interface{}{
new(func(string, map[string]any) bool),
},
},
{
name: "LogInfo",
function: LogInfo,
signature: []interface{}{
new(func(string, ...interface{}) bool),
},
},
{
name: "B64Decode",
function: B64Decode,
signature: []interface{}{
new(func(string) string),
},
},
{
name: "UnmarshalJSON",
function: UnmarshalJSON,
signature: []interface{}{
new(func(string, map[string]interface{}, string) error),
},
},
{
name: "ParseKV",
function: ParseKV,
signature: []interface{}{
new(func(string, map[string]interface{}, string) error),
},
},
{
name: "Hostname",
function: Hostname,
signature: []interface{}{
new(func() (string, error)),
},
},
{
name: "FloatApproxEqual",
function: FloatApproxEqual,
signature: []interface{}{
new(func(float64, float64) bool),
},
},
}
//go 1.20 "CutPrefix": strings.CutPrefix,
//go 1.20 "CutSuffix": strings.CutSuffix,
//"Cut": strings.Cut, -> returns more than 2 values, not supported by expr