diff --git a/integration_tests/http/dsl-functions.yaml b/integration_tests/http/dsl-functions.yaml index a86e6365..f0d43e57 100644 --- a/integration_tests/http/dsl-functions.yaml +++ b/integration_tests/http/dsl-functions.yaml @@ -81,6 +81,10 @@ requests: 69: {{zlib("Hello")}} 70: {{zlib_decode(hex_decode("789cf248cdc9c907040000ffff058c01f5"))}} 71: {{hex_encode(aes_gcm("AES256Key-32Characters1234567890", "exampleplaintext"))}} + 72: {{starts_with("Hello", "He")}} + 73: {{ends_with("Hello", "lo")}} + 74: {{line_starts_with("Hi\nHello", "He")}} + 75: {{line_ends_with("Hello\nHi", "lo")}} extractors: - type: regex diff --git a/v2/cmd/integration-test/http.go b/v2/cmd/integration-test/http.go index f58d2278..c4ca5e9a 100644 --- a/v2/cmd/integration-test/http.go +++ b/v2/cmd/integration-test/http.go @@ -256,7 +256,7 @@ func (h *httpDSLFunctions) Execute(filePath string) error { } totalExtracted := strings.Split(submatch[1], ",") - numberOfDslFunctions := 71 + numberOfDslFunctions := 75 if len(totalExtracted) != numberOfDslFunctions { return errors.New("incorrect number of results") } diff --git a/v2/pkg/operators/common/dsl/dsl.go b/v2/pkg/operators/common/dsl/dsl.go index 79877e58..1df0763f 100644 --- a/v2/pkg/operators/common/dsl/dsl.go +++ b/v2/pkg/operators/common/dsl/dsl.go @@ -246,6 +246,64 @@ func init() { "contains": makeDslFunction(2, func(args ...interface{}) (interface{}, error) { return strings.Contains(types.ToString(args[0]), types.ToString(args[1])), nil }), + "starts_with": makeDslWithOptionalArgsFunction( + "(str string, prefix ...string) bool", + func(args ...interface{}) (interface{}, error) { + if len(args) < 2 { + return nil, invalidDslFunctionError + } + for _, prefix := range args[1:] { + if strings.HasPrefix(types.ToString(args[0]), types.ToString(prefix)) { + return true, nil + } + } + return false, nil + }, + ), + "line_starts_with": makeDslWithOptionalArgsFunction( + "(str string, prefix ...string) bool", func(args ...interface{}) (interface{}, error) { + if len(args) < 2 { + return nil, invalidDslFunctionError + } + for _, line := range strings.Split(types.ToString(args[0]), "\n") { + for _, prefix := range args[1:] { + if strings.HasPrefix(line, types.ToString(prefix)) { + return true, nil + } + } + } + return false, nil + }, + ), + "ends_with": makeDslWithOptionalArgsFunction( + "(str string, suffix ...string) bool", + func(args ...interface{}) (interface{}, error) { + if len(args) < 2 { + return nil, invalidDslFunctionError + } + for _, suffix := range args[1:] { + if strings.HasSuffix(types.ToString(args[0]), types.ToString(suffix)) { + return true, nil + } + } + return false, nil + }, + ), + "line_ends_with": makeDslWithOptionalArgsFunction( + "(str string, suffix ...string) bool", func(args ...interface{}) (interface{}, error) { + if len(args) < 2 { + return nil, invalidDslFunctionError + } + for _, line := range strings.Split(types.ToString(args[0]), "\n") { + for _, suffix := range args[1:] { + if strings.HasSuffix(line, types.ToString(suffix)) { + return true, nil + } + } + } + return false, nil + }, + ), "concat": makeDslWithOptionalArgsFunction( "(args ...interface{}) string", func(arguments ...interface{}) (interface{}, error) { diff --git a/v2/pkg/operators/common/dsl/dsl_test.go b/v2/pkg/operators/common/dsl/dsl_test.go index 5f27867a..c5f7a3f4 100644 --- a/v2/pkg/operators/common/dsl/dsl_test.go +++ b/v2/pkg/operators/common/dsl/dsl_test.go @@ -142,6 +142,7 @@ func TestGetPrintableDslFunctionSignatures(t *testing.T) { contains(arg1, arg2 interface{}) interface{} date_time(dateTimeFormat string, optionalUnixTime interface{}) string dec_to_hex(arg1 interface{}) interface{} + ends_with(str string, suffix ...string) bool generate_java_gadget(arg1, arg2, arg3 interface{}) interface{} gzip(arg1 interface{}) interface{} gzip_decode(arg1 interface{}) interface{} @@ -152,6 +153,8 @@ func TestGetPrintableDslFunctionSignatures(t *testing.T) { html_unescape(arg1 interface{}) interface{} join(separator string, elements ...interface{}) string len(arg1 interface{}) interface{} + line_ends_with(str string, suffix ...string) bool + line_starts_with(str string, prefix ...string) bool md5(arg1 interface{}) interface{} mmh3(arg1 interface{}) interface{} print_debug(args ...interface{}) @@ -170,6 +173,7 @@ func TestGetPrintableDslFunctionSignatures(t *testing.T) { reverse(arg1 interface{}) interface{} sha1(arg1 interface{}) interface{} sha256(arg1 interface{}) interface{} + starts_with(str string, prefix ...string) bool to_lower(arg1 interface{}) interface{} to_number(arg1 interface{}) interface{} to_string(arg1 interface{}) interface{} @@ -248,6 +252,10 @@ func TestDslExpressions(t *testing.T) { `len("Hello")`: float64(5), `len(1234)`: float64(4), `contains("Hello", "lo")`: true, + `starts_with("Hello", "He")`: true, + `ends_with("Hello", "lo")`: true, + "line_starts_with('Hi\nHello', 'He')": true, // back quotes do not support escape sequences + "line_ends_with('Hii\nHello', 'ii')": true, // back quotes do not support escape sequences `regex("H([a-z]+)o", "Hello")`: true, `wait_for(1)`: nil, `print_debug(1+2, "Hello")`: nil,