EQL: Give a name to all toml tests and enforce the naming of new tests (#59283) (#59295)

(cherry picked from commit c8ffe3c9237d3cdd90331795b8e37517155b7e91)
This commit is contained in:
Andrei Stefan 2020-07-09 16:20:29 +03:00 committed by GitHub
parent 5debd09808
commit d187b531ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 449 additions and 24 deletions

View File

@ -26,7 +26,9 @@ import org.junit.BeforeClass;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import static java.util.stream.Collectors.toList;
@ -61,9 +63,10 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
public static List<Object[]> readTestSpecs() throws Exception {
// Load EQL validation specs
List<EqlSpec> specs = EqlSpecLoader.load("/test_queries.toml", true);
specs.addAll(EqlSpecLoader.load("/additional_test_queries.toml", true));
List<EqlSpec> unsupportedSpecs = EqlSpecLoader.load("/test_queries_unsupported.toml", false);
Set<String> uniqueTestNames = new HashSet<>();
List<EqlSpec> specs = EqlSpecLoader.load("/test_queries.toml", true, uniqueTestNames);
specs.addAll(EqlSpecLoader.load("/additional_test_queries.toml", true, uniqueTestNames));
List<EqlSpec> unsupportedSpecs = EqlSpecLoader.load("/test_queries_unsupported.toml", false, uniqueTestNames);
// Validate only currently supported specs
List<EqlSpec> filteredSpecs = new ArrayList<>();
@ -89,7 +92,7 @@ public abstract class CommonEqlActionTestCase extends ESRestTestCase {
private static List<Object[]> asArray(List<EqlSpec> specs) {
AtomicInteger counter = new AtomicInteger();
return specs.stream().map(spec -> {
String name = spec.description();
String name = spec.name();
if (Strings.isNullOrEmpty(name)) {
name = spec.note();
}

View File

@ -12,6 +12,7 @@ import java.util.Arrays;
import java.util.Objects;
public class EqlSpec {
private String name;
private String description;
private String note;
private String[] tags;
@ -24,6 +25,14 @@ public class EqlSpec {
// FALSE -> case insensitive
private Boolean caseSensitive = null;
public String name() {
return name;
}
public void name(String name) {
this.name = name;
}
public String description() {
return description;
}
@ -76,6 +85,7 @@ public class EqlSpec {
public String toString() {
String str = "";
str = appendWithComma(str, "query", query);
str = appendWithComma(str, "name", name);
str = appendWithComma(str, "description", description);
str = appendWithComma(str, "note", note);

View File

@ -9,26 +9,40 @@ package org.elasticsearch.test.eql;
import io.ous.jtoml.JToml;
import io.ous.jtoml.Toml;
import io.ous.jtoml.TomlTable;
import org.elasticsearch.common.Strings;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
public class EqlSpecLoader {
public static List<EqlSpec> load(String path, boolean supported) throws Exception {
public static List<EqlSpec> load(String path, boolean supported, Set<String> uniqueTestNames) throws Exception {
try (InputStream is = EqlSpecLoader.class.getResourceAsStream(path)) {
return readFromStream(is, supported);
return readFromStream(is, supported, uniqueTestNames);
}
}
private static void validateAndAddSpec(List<EqlSpec> specs, EqlSpec spec, boolean supported) throws Exception {
private static void validateAndAddSpec(List<EqlSpec> specs, EqlSpec spec, boolean supported,
Set<String> uniqueTestNames) throws Exception {
if (Strings.isNullOrEmpty(spec.name())) {
throw new IllegalArgumentException("Read a test without a name value");
}
if (Strings.isNullOrEmpty(spec.query())) {
throw new IllegalArgumentException("Read a test without a query value");
}
if (supported && spec.expectedEventIds() == null) {
throw new IllegalArgumentException("Read a test without a expected_event_ids value");
if (supported) {
if (spec.expectedEventIds() == null) {
throw new IllegalArgumentException("Read a test without a expected_event_ids value");
}
if (uniqueTestNames.contains(spec.name())) {
throw new IllegalArgumentException("Found a test with the same name as another test: " + spec.name());
} else {
uniqueTestNames.add(spec.name());
}
}
specs.add(spec);
@ -42,7 +56,7 @@ public class EqlSpecLoader {
return null;
}
private static List<EqlSpec> readFromStream(InputStream is, boolean supported) throws Exception {
private static List<EqlSpec> readFromStream(InputStream is, boolean supported, Set<String> uniqueTestNames) throws Exception {
List<EqlSpec> testSpecs = new ArrayList<>();
EqlSpec spec;
@ -52,6 +66,7 @@ public class EqlSpecLoader {
for (TomlTable table : queries) {
spec = new EqlSpec();
spec.query(getTrimmedString(table, "query"));
spec.name(getTrimmedString(table, "name"));
spec.note(getTrimmedString(table, "note"));
spec.description(getTrimmedString(table, "description"));
@ -88,7 +103,7 @@ public class EqlSpecLoader {
}
spec.expectedEventIds(expectedEventIds);
}
validateAndAddSpec(testSpecs, spec, supported);
validateAndAddSpec(testSpecs, spec, supported, uniqueTestNames);
}
return testSpecs;

View File

@ -2,48 +2,56 @@
# test_queries.toml file in order to keep the original unchanged and easier to sync with the EQL reference implementation tests.
[[queries]]
name = "betweenAdditional1"
expected_event_ids = [95]
query = '''
file where between(file_path, "dev", ".json", false) == "\\TestLogs\\something"
'''
[[queries]]
name = "betweenAdditional2"
expected_event_ids = [95]
query = '''
file where between(file_path, "dev", ".json", true) == "\\TestLogs\\something"
'''
[[queries]]
name = "stringCidrMatch1"
expected_event_ids = [75304, 75305]
query = '''
network where cidrMatch(source_address, "10.6.48.157/8") == true
'''
[[queries]]
name = "stringCidrMatch2"
expected_event_ids = [75304, 75305]
query = '''
network where string(cidrMatch(source_address, "10.6.48.157/8")) == "true"
'''
[[queries]]
name = "cidrMatchAdditional2"
expected_event_ids = [75304, 75305]
query = '''
network where true == cidrMatch(source_address, "10.6.48.157/8")
'''
[[queries]]
name = "cidrMatchAdditional3"
expected_event_ids = []
query = '''
network where cidrMatch(source_address, "192.168.0.0/16") == true
'''
[[queries]]
name = "cidrMatchAdditional4"
expected_event_ids = [75304, 75305]
query = '''
network where cidrMatch(source_address, "192.168.0.0/16", "10.6.48.157/8") == true
'''
[[queries]]
name = "cidrMatchAdditional5"
expected_event_ids = [75304, 75305]
query = '''
network where cidrMatch(source_address, "0.0.0.0/0") == true
@ -51,6 +59,7 @@ network where cidrMatch(source_address, "0.0.0.0/0") == true
[[queries]]
name = "concatEquals1"
description = "test string concatenation. update test to avoid case-sensitivity issues"
query = '''
process where concat(serial_event_id, '::', process_name, '::', opcode) == '5::wininit.exe::3'
@ -59,60 +68,72 @@ expected_event_ids = [5]
[[queries]]
name = "concatEquals2"
query = 'process where concat(serial_event_id) = "1"'
expected_event_ids = [1]
[[queries]]
name = "concatWithCondition1"
query = 'process where serial_event_id < 5 and concat(process_name, parent_process_name) != null'
expected_event_ids = [2, 3]
[[queries]]
name = "concatWithCondition2"
query = 'process where serial_event_id < 5 and concat(process_name, parent_process_name) == null'
expected_event_ids = [1, 4]
[[queries]]
name = "concatWithCondition3"
query = 'process where serial_event_id < 5 and concat(process_name, null, null) == null'
expected_event_ids = [1, 2, 3, 4]
[[queries]]
name = "concatWithCondition4"
query = 'process where serial_event_id < 5 and concat(parent_process_name, null) == null'
expected_event_ids = [1, 2, 3, 4]
[[queries]]
name = "numberStringConversion1"
query = 'process where string(serial_event_id) = "1"'
expected_event_ids = [1]
[[queries]]
name = "numberStringConversion2"
query = 'any where number(string(serial_event_id)) == 17'
expected_event_ids = [17]
[[queries]]
name = "numberStringConversion3"
query = 'any where number(string(serial_event_id), null) == 17'
expected_event_ids = [17]
[[queries]]
name = "numberStringConversion4"
query = 'any where number(string(serial_event_id), 10) == 17'
expected_event_ids = [17]
[[queries]]
name = "numberStringEquality"
query = 'any where number(string(serial_event_id), 13) == number("31", 13)'
expected_event_ids = [31]
[[queries]]
name = "numberStringConversion5"
query = 'any where number(string(serial_event_id), 16) == 17'
expected_event_ids = [11]
[[queries]]
name = "matchWithCharacterClasses1"
expected_event_ids = [98]
notes = "regexp doesn't support character classes"
query = '''
@ -122,12 +143,14 @@ process where match(command_line, ?'.*?net1[ ]+localgroup.*?')
'''
[[queries]]
name = "matchLiteAdditional"
expected_event_ids = [98]
query = '''
process where matchLite(command_line, ?'.*?net1.*?')
'''
[[queries]]
name = "matchWithCharacterClasses2"
expected_event_ids = [98]
notes = "regexp doesn't support predefined character classes (like \\s)"
query = '''
@ -138,18 +161,21 @@ process where match(command_line, ?'.*?net1[ ]+[a-z]{4,15}[ ]+.*?')
[[queries]]
name = "multiPatternMatch"
expected_event_ids = [50, 97, 98]
query = '''
process where match(command_line, '.*?net[1]? localgroup.*?', '.*? myappserver.py .*?')
'''
[[queries]]
name = "matchWithSubstring"
expected_event_ids = [50, 98]
query = '''
process where match(substring(command_line, 5), '.*?net[1]? localgroup.*?', '.*? myappserver.py .*?')
'''
[[queries]]
name = "moduloEqualsField"
# Basic test for modulo function
query = '''
process where modulo(11, 10) == serial_event_id'''
@ -157,36 +183,44 @@ expected_event_ids = [1]
description = "test built-in modulo math functions"
[[queries]]
name = "additionalMathWithFields1"
# This query give a different result with ES EQL implementation because it doesn't convert to float data types for division
expected_event_ids = [82, 83]
query = "file where serial_event_id / 2 == 41"
# Additional EQL queries with arithmetic operations that were not part of the original EQL implementation
[[queries]]
name = "additionalMathWithFields2"
expected_event_ids = [82]
query = "file where 83 - serial_event_id == 1"
[[queries]]
name = "additionalMathWithFields3"
expected_event_ids = [82]
query = "file where 1 + serial_event_id == 83"
[[queries]]
name = "additionalMathWithFields4"
expected_event_ids = [82]
query = "file where -serial_event_id + 100 == 18"
[[queries]]
name = "additionalMathWithFields5"
expected_event_ids = [82]
query = "file where 2 * serial_event_id == 164"
[[queries]]
name = "additionalMathWithFields6"
expected_event_ids = [66]
query = "file where 66.0 / serial_event_id == 1"
[[queries]]
name = "additionalMathWithFields7"
expected_event_ids = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 46]
query = "process where serial_event_id + ((1 + 3) * 2 / (3 - 1)) * 2 == 54 or 70 + serial_event_id < 100"
[[queries]]
name = "twoSequencesAdditional1"
query = '''
sequence
[process where serial_event_id = 1]
@ -195,6 +229,7 @@ sequence
expected_event_ids = [1, 2]
[[queries]]
name = "twoSequencesAdditional2"
query = '''
sequence
[process where serial_event_id=1] by unique_pid
@ -202,6 +237,7 @@ sequence
expected_event_ids = [1, 2]
[[queries]]
name = "twoSequencesAdditional3"
query = '''
sequence
[process where serial_event_id<3] by unique_pid
@ -210,6 +246,7 @@ sequence
expected_event_ids = [1, 2, 2, 3]
[[queries]]
name = "twoSequencesAdditional4"
query = '''
sequence
[process where false] by unique_pid

View File

@ -8,12 +8,8 @@
# in order to allow at least one round-trip test with the test harness.
# This will be removed once the EQL implementation is wired and actually supports this query.
[[queries]]
expected_event_ids = []
query = 'process where missing_field != null'
[[queries]]
name = "twoSequencesWithKeys"
query = '''
sequence
[process where true] by unique_pid
@ -25,6 +21,7 @@ expected_event_ids = [48, 53,
97, 98]
[[queries]]
name = "twoSequencesWithTwoKeys"
query = '''
sequence
[process where true] by unique_pid, process_path
@ -40,15 +37,18 @@ expected_event_ids = [48, 53,
#############################
[[queries]]
name = "missingField1"
expected_event_ids = []
query = 'process where missing_field != null'
[[queries]]
name = "equalsNullHead"
expected_event_ids = [1, 2, 3, 4, 5]
query = 'process where bad_field == null | head 5'
[[queries]]
name = "lteAndGtWithFilter"
tags = ["comparisons", "pipes"]
query = '''
process where serial_event_id <= 8 and serial_event_id > 7
@ -57,6 +57,7 @@ process where serial_event_id <= 8 and serial_event_id > 7
expected_event_ids = [8]
[[queries]]
name = "filtersLteAndGt"
query = '''
process where true
| filter serial_event_id <= 10
@ -65,6 +66,7 @@ process where true
expected_event_ids = [7, 8, 9, 10]
[[queries]]
name = "filterLteAndGtWithHead"
query = '''
process where true
| filter serial_event_id <= 10
@ -74,6 +76,7 @@ process where true
expected_event_ids = [7, 8]
[[queries]]
name = "headWithFiltersAndTail"
query = '''
process where true
| head 1000
@ -84,15 +87,18 @@ process where true
expected_event_ids = [9, 10]
[[queries]]
name = "processWithMultipleConditions2"
query = 'process where (serial_event_id<9 and serial_event_id >= 7) or (opcode == pid)'
expected_event_ids = [7, 8]
[[queries]]
name = "compareTwoFields1"
case_insensitive = true
query = 'process where serial_event_id < 5 and process_name <= parent_process_name'
expected_event_ids = [2, 3]
[[queries]]
name = "compareTwoFields2"
case_sensitive = true
query = 'process where serial_event_id < 5 and process_name <= parent_process_name'
expected_event_ids = [2]
@ -100,27 +106,32 @@ expected_event_ids = [2]
[[queries]]
name = "processWithStringComparisonCaseInsensitive1"
case_insensitive = true
query = 'process where process_name >= "system idle process" and process_name <= "System Idle Process"'
expected_event_ids = [1]
[[queries]]
name = "processWithStringComparisonCaseInsensitive2"
case_insensitive = true
query = 'process where process_name >= "SYSTE" and process_name < "systex"'
expected_event_ids = [1, 2]
[[queries]]
name = "processWithStringComparisonCaseInsensitive3"
case_insensitive = true
query = 'process where process_name >= "sysT" and process_name < "SYsTeZZZ"'
expected_event_ids = [1, 2]
[[queries]]
name = "processWithStringComparisonCaseInsensitive4"
case_insensitive = true
query = 'process where process_name >= "SYSTE" and process_name <= "systex"'
expected_event_ids = [1, 2]
[[queries]]
name = "processWithStringEqualityCaseInsensitive1"
case_insensitive = true
query = '''
process where process_name == "VMACTHLP.exe" and unique_pid == 12
@ -129,6 +140,7 @@ process where process_name == "VMACTHLP.exe" and unique_pid == 12
expected_event_ids = [12]
[[queries]]
name = "processNameIN"
query = '''
process where process_name in ("python.exe", "smss.exe", "explorer.exe")
| unique process_name
@ -136,6 +148,7 @@ process where process_name in ("python.exe", "smss.exe", "explorer.exe")
expected_event_ids = [3, 34, 48]
[[queries]]
name = "processNameINCaseInsensitive1"
case_insensitive = true
query = '''
process where process_name in ("python.exe", "SMSS.exe", "explorer.exe")
@ -144,6 +157,7 @@ process where process_name in ("python.exe", "SMSS.exe", "explorer.exe")
expected_event_ids = [3, 34, 48]
[[queries]]
name = "processNameINCaseInsensitive2"
case_insensitive = true
query = '''
process where process_name in ("python.exe", "smss.exe", "Explorer.exe")
@ -152,6 +166,7 @@ process where process_name in ("python.exe", "smss.exe", "Explorer.exe")
expected_event_ids = [3, 34, 48]
[[queries]]
name = "processNameINWithUnique1"
query = '''
process where process_name in ("python.exe", "smss.exe", "explorer.exe")
| unique length(process_name) == length("python.exe")
@ -159,6 +174,7 @@ process where process_name in ("python.exe", "smss.exe", "explorer.exe")
expected_event_ids = [3, 48]
[[queries]]
name = "processNameINWithUnique2"
case_insensitive = true
query = '''
process where process_name in ("Python.exe", "smss.exe", "explorer.exe")
@ -167,6 +183,7 @@ process where process_name in ("Python.exe", "smss.exe", "explorer.exe")
expected_event_ids = [3, 48]
[[queries]]
name = "processNameINWithUniqueHeadAndTail1"
query = '''
process where process_name in ("python.exe", "smss.exe", "explorer.exe")
| unique process_name
@ -176,6 +193,7 @@ process where process_name in ("python.exe", "smss.exe", "explorer.exe")
expected_event_ids = [34]
[[queries]]
name = "processNameINWithUniqueHeadAndTail2"
query = '''
process where process_name in ("python.exe", "smss.exe", "explorer.exe")
| unique process_name
@ -185,6 +203,7 @@ process where process_name in ("python.exe", "smss.exe", "explorer.exe")
expected_event_ids = [34]
[[queries]]
name = "processNameINWithUnique3"
query = '''
process where process_name in ("python.exe", "smss.exe")
| unique process_name parent_process_name
@ -192,6 +211,7 @@ process where process_name in ("python.exe", "smss.exe")
expected_event_ids = [3, 48, 50, 54, 78]
[[queries]]
name = "processNameINWithTwoUniqueFields1"
query = '''
process where process_name in ("python.exe", "smss.exe")
| unique process_name, parent_process_name
@ -199,6 +219,7 @@ process where process_name in ("python.exe", "smss.exe")
expected_event_ids = [3, 48, 50, 54, 78]
[[queries]]
name = "processNameINWithTwoUniqueFields2"
query = '''
process where process_name in ("python.exe", "smss.exe")
| head 5
@ -207,6 +228,7 @@ process where process_name in ("python.exe", "smss.exe")
expected_event_ids = [3, 48, 50, 54]
[[queries]]
name = "lengthCaseInsensitive"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -214,6 +236,7 @@ registry where length(bytes_written_string_list) == 2 and bytes_written_string_l
'''
[[queries]]
name = "descendant1"
query = '''
file where file_name == "csrss.exe" and opcode=0
and descendant of [process where opcode in (1,3) and process_name="cmd.exe"]
@ -221,6 +244,7 @@ file where file_name == "csrss.exe" and opcode=0
expected_event_ids = [72]
[[queries]]
name = "descendant2"
query = '''
process where opcode=1 and process_name == "csrss.exe"
and descendant of [file where file_name == "csrss.exe" and opcode=0]
@ -228,6 +252,7 @@ process where opcode=1 and process_name == "csrss.exe"
expected_event_ids = [73]
[[queries]]
name = "descendant3"
query = '''
process where opcode=1 and process_name == "smss.exe"
and descendant of [
@ -241,6 +266,7 @@ expected_event_ids = [78]
[[queries]]
name = "simpleTail"
query = '''
file where true
| tail 3
@ -248,12 +274,14 @@ file where true
expected_event_ids = [92, 95, 96]
[[queries]]
name = "twoINs"
query = '''
process where opcode in (1,3) and process_name in (parent_process_name, "System")
'''
expected_event_ids = [2, 50, 51]
[[queries]]
name = "twoINsCaseInsensitive"
case_insensitive = true
query = '''
process where opcode in (1,3) and process_name in (parent_process_name, "SYSTEM")
@ -261,6 +289,7 @@ process where opcode in (1,3) and process_name in (parent_process_name, "SYSTEM"
expected_event_ids = [2, 50, 51]
[[queries]]
name = "simpleTailWithSort"
case_insensitive = true
expected_event_ids = [92, 95, 96, 91]
query = '''
@ -270,6 +299,7 @@ file where true
'''
[[queries]]
name = "simpleHeadWithSort1"
expected_event_ids = [2, 1, 4, 3, 5]
query = '''
process where true
@ -278,6 +308,7 @@ process where true
'''
[[queries]]
name = "simpleHeadWithSort2"
expected_event_ids = [2, 1, 4, 3, 5]
query = '''
process where true
@ -286,6 +317,7 @@ process where true
'''
[[queries]]
name = "simpleHeadWithSort3"
expected_event_ids = [2, 1, 4, 3, 5]
query = '''
process where true
@ -294,6 +326,7 @@ process where true
'''
[[queries]]
name = "twoHeadsWithSort"
expected_event_ids = [2, 1]
query = '''
process where true
@ -303,6 +336,7 @@ process where true
'''
[[queries]]
name = "twoSortsWithHead"
expected_event_ids = [1, 2, 3, 4, 5]
query = '''
process where true
@ -313,6 +347,7 @@ process where true
[[queries]]
name = "fourSequencesByPidWithUntil1"
query = '''
sequence
[process where opcode == 1] by unique_pid
@ -325,6 +360,7 @@ until
expected_event_ids = []
[[queries]]
name = "fourSequencesByPidWithUntil2"
query = '''
sequence
[process where opcode == 1] by unique_pid
@ -337,6 +373,7 @@ until
expected_event_ids = [54, 55, 61, 67]
[[queries]]
name = "doubleSameSequenceWithByAndFilter"
query = '''
sequence
[file where opcode=0] by unique_pid
@ -346,6 +383,7 @@ sequence
expected_event_ids = [87, 92]
[[queries]]
name = "doubleSameSequenceWithByUntilAndHead2"
query = '''
sequence
[file where opcode=0 and file_name="*.exe"] by unique_pid
@ -356,6 +394,7 @@ until [process where opcode=1] by unique_ppid
expected_event_ids = []
[[queries]]
name = "doubleJoinWithByUntilAndHead"
query = '''
join
[file where opcode=0 and file_name="*.exe"] by unique_pid
@ -366,6 +405,7 @@ until [process where opcode=1] by unique_ppid
expected_event_ids = [61, 59]
[[queries]]
name = "twoJoins1"
query = '''
join by user_name
[process where opcode in (1,3) and process_name="smss.exe"]
@ -374,6 +414,7 @@ join by user_name
expected_event_ids = [78, 48]
[[queries]]
name = "threeJoins1"
query = '''
join by unique_pid
[process where opcode=1]
@ -383,6 +424,7 @@ join by unique_pid
expected_event_ids = [54, 55, 61]
[[queries]]
name = "threeJoins2"
query = '''
join by string(unique_pid)
[process where opcode=1]
@ -392,6 +434,7 @@ join by string(unique_pid)
expected_event_ids = [54, 55, 61]
[[queries]]
name = "threeJoinsWithUntil1"
query = '''
join by unique_pid
[process where opcode=1]
@ -402,6 +445,7 @@ until [file where opcode == 2]
expected_event_ids = []
[[queries]]
name = "threeJoinsWithUntil1"
query = '''
join by string(unique_pid), unique_pid, unique_pid * 2
[process where opcode=1]
@ -412,6 +456,7 @@ until [file where opcode == 2]
expected_event_ids = []
[[queries]]
name = "twoJoins2"
query = '''
join
[file where opcode=0 and file_name="svchost.exe"] by unique_pid
@ -420,6 +465,7 @@ join
expected_event_ids = [55, 56]
[[queries]]
name = "twoJoins3"
query = '''
join by unique_pid
[process where opcode in (1,3) and process_name="python.exe"]
@ -428,6 +474,7 @@ join by unique_pid
expected_event_ids = [54, 55]
[[queries]]
name = "twoJoins4"
query = '''
join by user_name
[process where opcode in (1,3) and process_name="python.exe"]
@ -436,6 +483,7 @@ join by user_name
expected_event_ids = [48, 78]
[[queries]]
name = "twoJoins5"
query = '''
join
[process where opcode in (1,3) and process_name="python.exe"]
@ -444,12 +492,14 @@ join
expected_event_ids = [48, 3, 50, 78]
[[queries]]
name = "fakeField"
expected_event_ids = []
query = '''
process where fake_field == "*"
'''
[[queries]]
name = "fakeFieldWithHead1"
# no longer valid, since this returns `null`, and `not null` is still null
# expected_event_ids = [1, 2, 3, 4]
expected_event_ids = []
@ -459,6 +509,7 @@ process where fake_field != "*"
'''
[[queries]]
name = "fakeFieldWithHead2"
# no longer valid, since this returns `null`, and `not null` is still null
# expected_event_ids = [1, 2, 3, 4]
expected_event_ids = []
@ -468,52 +519,62 @@ process where not (fake_field == "*")
'''
[[queries]]
name = "invalidFieldName"
expected_event_ids = []
query = '''
registry where invalid_field_name != null
'''
[[queries]]
name = "badFieldWithLength"
expected_event_ids = []
query = '''
registry where length(bad_field) > 0
'''
[[queries]]
name = "equalsNullHead"
expected_event_ids = [1, 2, 3, 4, 5]
query = 'process where bad_field == null | head 5'
[[queries]]
name = "exitCodeGtZero"
note = "check that comparisons against null values return false"
expected_event_ids = [58, 64, 69, 74, 80, 85, 90, 93, 94, 75303]
query = 'process where exit_code >= 0'
[[queries]]
name = "zeroLteExitCode"
note = "check that comparisons against null values return false"
expected_event_ids = [58, 64, 69, 74, 80, 85, 90, 93, 94, 75303]
query = 'process where 0 <= exit_code'
[[queries]]
name = "exitCodeLteZero"
note = "check that comparisons against null values return false"
expected_event_ids = [58, 64, 69, 74, 80, 85, 90, 93, 94, 75303]
query = 'process where exit_code <= 0'
[[queries]]
name = "exitCodeLtOne"
note = "check that comparisons against null values return false"
expected_event_ids = [58, 64, 69, 74, 80, 85, 90, 93, 94, 75303]
query = 'process where exit_code < 1'
[[queries]]
name = "exitCodeGtMinusOne"
note = "check that comparisons against null values return false"
expected_event_ids = [58, 64, 69, 74, 80, 85, 90, 93, 94, 75303]
query = 'process where exit_code > -1'
[[queries]]
name = "minusOneLtExitCode"
note = "check that comparisons against null values return false"
expected_event_ids = [58, 64, 69, 74, 80, 85, 90, 93, 94, 75303]
query = 'process where -1 < exit_code'
[[queries]]
name = "notExitCodeGtWithHead1"
note = "check that comparisons against null values return false"
expected_event_ids = []
query = '''
@ -523,16 +584,19 @@ process where not (exit_code > -1)
'''
[[queries]]
name = "notExitCodeGtWithHead2"
note = "check that comparisons against null values return false"
expected_event_ids = [1, 2, 3, 4, 5, 6, 7]
query = 'process where not (exit_code > -1) | head 7'
[[queries]]
name = "notExitCodeGtWithHead3"
note = "check that comparisons against null values return false"
expected_event_ids = [1, 2, 3, 4, 5, 6, 7]
query = 'process where not (-1 < exit_code) | head 7'
[[queries]]
name = "anyWithUnique"
expected_event_ids = [1, 55, 57, 63, 75304]
query = '''
any where true
@ -540,6 +604,7 @@ any where true
'''
[[queries]]
name = "multipleConditionsWithDescendant1"
query = '''
process where opcode=1 and process_name in ("services.exe", "smss.exe", "lsass.exe")
and descendant of [process where process_name == "cmd.exe" ]
@ -547,6 +612,7 @@ process where opcode=1 and process_name in ("services.exe", "smss.exe", "lsass.e
expected_event_ids = [62, 68, 78]
[[queries]]
name = "INWithDescendant"
query = '''
process where process_name in ("services.exe", "smss.exe", "lsass.exe")
and descendant of [process where process_name == "cmd.exe" ]
@ -554,6 +620,7 @@ process where process_name in ("services.exe", "smss.exe", "lsass.exe")
expected_event_ids = [62, 64, 68, 69, 78, 80]
[[queries]]
name = "multipleConditionsWithDescendant2"
query = '''
process where opcode=2 and process_name in ("services.exe", "smss.exe", "lsass.exe")
and descendant of [process where process_name == "cmd.exe" ]
@ -561,6 +628,7 @@ process where opcode=2 and process_name in ("services.exe", "smss.exe", "lsass.e
expected_event_ids = [64, 69, 80]
[[queries]]
name = "childOf1"
query = '''
process where process_name="svchost.exe"
and child of [file where file_name="svchost.exe" and opcode=0]
@ -568,6 +636,7 @@ process where process_name="svchost.exe"
expected_event_ids = [56, 58]
[[queries]]
name = "childOf2"
query = '''
process where process_name="svchost.exe"
and not child of [file where file_name="svchost.exe" and opcode=0]
@ -576,6 +645,7 @@ process where process_name="svchost.exe"
expected_event_ids = [11, 13, 15]
[[queries]]
name = "nestedChildOf1"
query = '''
process where process_name="lsass.exe"
and child of [
@ -586,6 +656,7 @@ process where process_name="lsass.exe"
expected_event_ids = [62, 64]
[[queries]]
name = "nestedChildOf2"
query = '''
file where child of [
process where child of [
@ -597,6 +668,7 @@ file where child of [
expected_event_ids = [91]
[[queries]]
name = "fileByUniquePid1"
query = '''
file where process_name = "python.exe"
| unique unique_pid
@ -604,6 +676,7 @@ file where process_name = "python.exe"
expected_event_ids = [55, 95]
[[queries]]
name = "fileByUniquePid2"
query = '''
file where event of [process where process_name = "python.exe" ]
| unique unique_pid
@ -611,16 +684,19 @@ file where event of [process where process_name = "python.exe" ]
expected_event_ids = [55, 95]
[[queries]]
name = "simpleStringEquality"
query = '''
process where process_name = "python.exe"
'''
expected_event_ids = [48, 50, 51, 54, 93]
[[queries]]
name = "eventOfProcess"
query = 'process where event of [process where process_name = "python.exe" ]'
expected_event_ids = [48, 50, 51, 54, 93]
[[queries]]
name = "twoSequencesWithTwoKeysAndUntil"
query = '''
sequence by user_name
[file where opcode=0] by pid,file_path
@ -631,6 +707,7 @@ until
expected_event_ids = []
[[queries]]
name = "twoSequencesWithUntil"
query = '''
sequence by user_name
[file where opcode=0] by pid,file_path
@ -642,6 +719,7 @@ until
expected_event_ids = [55, 59, 61, 65]
[[queries]]
name = "twoSequencesWithHead"
query = '''
join by user_name
[file where true] by pid,file_path
@ -651,6 +729,7 @@ join by user_name
expected_event_ids = [55, 56, 59, 58]
[[queries]]
name = "threeSequencesWithHead"
query = '''
sequence
[process where true] by unique_pid
@ -661,6 +740,7 @@ sequence
expected_event_ids = [54, 55, 56, 54, 61, 62, 54, 67, 68, 54, 72, 73]
[[queries]]
name = "uniqueCount1"
expected_event_ids = [11, 60, 63]
query = '''
any where process_name == "svchost.exe"
@ -668,6 +748,7 @@ any where process_name == "svchost.exe"
'''
[[queries]]
name = "uniqueCount2"
expected_event_ids = [63, 60, 11]
query = '''
any where process_name == "svchost.exe"
@ -676,6 +757,7 @@ any where process_name == "svchost.exe"
'''
[[queries]]
name = "uniqueCount3"
expected_event_ids = [60]
query = '''
any where process_name == "svchost.exe"
@ -684,6 +766,7 @@ any where process_name == "svchost.exe"
'''
[[queries]]
name = "uniqueCountAndFilter"
expected_event_ids = [11]
query = '''
any where process_name == "svchost.exe"
@ -693,6 +776,7 @@ any where process_name == "svchost.exe"
[[queries]]
name = "arrayContainsCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -700,6 +784,7 @@ registry where arrayContains(bytes_written_string_list, 'En-uS')
'''
[[queries]]
name = "arrayContainsCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -707,6 +792,7 @@ registry where arrayContains(bytes_written_string_list, 'En')
'''
[[queries]]
name = "lengthCaseInsensitive"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -714,6 +800,7 @@ registry where length(bytes_written_string_list) > 0 and bytes_written_string_li
'''
[[queries]]
name = "arrayCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -721,6 +808,7 @@ registry where bytes_written_string_list[0] == 'EN-us'
'''
[[queries]]
name = "arrayCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -729,6 +817,7 @@ registry where bytes_written_string_list[1] == 'EN'
[[queries]]
name = "arrayContainsCaseInsensitive3"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -736,6 +825,7 @@ registry where arrayContains(bytes_written_string_list, 'en-US')
'''
[[queries]]
name = "arrayContainsCaseInsensitive4"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -743,6 +833,7 @@ registry where arrayContains(bytes_written_string_list, 'en')
'''
[[queries]]
name = "arrayCaseInsensitive3"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -750,12 +841,14 @@ registry where length(bytes_written_string_list) > 0 and bytes_written_string_li
'''
[[queries]]
name = "arrayEquality1"
expected_event_ids = [57]
query = '''
registry where bytes_written_string_list[0] == 'en-US'
'''
[[queries]]
name = "arrayEquality2"
expected_event_ids = [57]
query = '''
registry where bytes_written_string_list[1] == 'en'
@ -763,36 +856,42 @@ registry where bytes_written_string_list[1] == 'en'
# character classes aren't supported. custom tests made in test_queries_supported.toml
[[queries]]
name = "matchLite1"
query = '''
process where matchLite(command_line, ?'.*?net1\s+localgroup\s+.*?')
'''
expected_event_ids = [98]
[[queries]]
name = "matchLite2"
query = '''
process where matchLite(command_line, ?'.*?net1\s+\w+\s+.*?')
'''
expected_event_ids = [98]
[[queries]]
name = "matchLite3"
query = '''
process where matchLite(command_line, ?'.*?net1\s+\w{4,15}\s+.*?')
'''
expected_event_ids = [98]
[[queries]]
name = "match1"
expected_event_ids = [98]
query = '''
process where match(command_line, ?'.*?net1\s+\w{4,15}\s+.*?')
'''
[[queries]]
name = "matchLite4"
query = '''
process where matchLite(command_line, ?'.*?net1\s+[localgrup]{4,15}\s+.*?')
'''
expected_event_ids = [98]
[[queries]]
name = "stringEqualsCaseInsensitive1"
case_insensitive = true
query = '''
process where 'net.EXE' == original_file_name
@ -802,6 +901,7 @@ expected_event_ids = [97]
note = "check that case insensitive comparisons are performed even for lhs strings."
[[queries]]
name = "stringEqualsCaseInsensitive2"
case_insensitive = true
query = '''
process where process_name == original_file_name and process_name='net*.exe'
@ -810,6 +910,7 @@ expected_event_ids = [97, 98]
note = "check that case insensitive comparisons are performed for fields."
[[queries]]
name = "fieldsComparisonCaseInsensitive"
case_insensitive = true
query = '''
process where original_file_name == process_name and length(original_file_name) > 0
@ -818,6 +919,7 @@ expected_event_ids = [97, 98, 75273, 75303]
description = "check that case insensitive comparisons are performed for fields."
[[queries]]
name = "substring3"
case_insensitive = true
query = '''
file where substring(file_name, 1, 3) == 'xp'
@ -826,6 +928,7 @@ expected_event_ids = [88, 91, 92]
description = "check substring ranges"
[[queries]]
name = "moduloEquals"
query = '''
process where modulo(11, add(serial_event_id, 1)) == serial_event_id
'''
@ -833,6 +936,7 @@ expected_event_ids = [1, 2, 3, 5, 11]
description = "test built-in math functions"
[[queries]]
name = "concatCaseInsensitive"
case_insensitive = true
query = '''
process where concat(serial_event_id, ':', process_name, opcode) == '5:winINIT.exe3'
@ -841,6 +945,7 @@ expected_event_ids = [5]
description = "test string concatenation"
[[queries]]
name = "fieldComparisonCaseInsensitive"
case_insensitive = true
query = '''
process where process_name != original_file_name and length(original_file_name) > 0
@ -850,6 +955,7 @@ description = "check that case insensitive comparisons are performed for fields.
[[queries]]
name = "arraySearch1"
expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects"
query = '''
@ -857,6 +963,7 @@ registry where arraySearch(bytes_written_string_list, a, a == 'en-US')
'''
[[queries]]
name = "arraySearchCaseSensitive"
case_sensitive = true
expected_event_ids = []
description = "test arraySearch functionality for lists of strings, and lists of objects"
@ -865,6 +972,7 @@ registry where arraySearch(bytes_written_string_list, a, a == 'EN-US')
'''
[[queries]]
name = "arraySearchCaseInsensitive1"
case_insensitive = true
expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects"
@ -873,6 +981,7 @@ registry where arraySearch(bytes_written_string_list, a, a == 'en-us')
'''
[[queries]]
name = "arraySearchCaseInsensitive2"
case_insensitive = true
expected_event_ids = [57]
description = "test arraySearch functionality for lists of strings, and lists of objects"
@ -881,6 +990,7 @@ registry where arraySearch(bytes_written_string_list, a, endsWith(a, '-us'))
'''
[[queries]]
name = "arraySearchWithMysteriousField1"
expected_event_ids = [75305]
description = "test arraySearch - true"
query = '''
@ -889,6 +999,7 @@ network where mysterious_field
'''
[[queries]]
name = "arraySearchWithMysteriousField2"
expected_event_ids = []
description = "test arraySearch - false"
query = '''
@ -896,6 +1007,7 @@ network where mysterious_field and arraySearch(mysterious_field.subarray, s, fal
'''
[[queries]]
name = "arraySearchWithMysteriousField3"
expected_event_ids = [75305]
description = "test arraySearch - conditional"
query = '''
@ -903,6 +1015,7 @@ network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a
'''
[[queries]]
name = "arraySearchWithMysteriousField4"
expected_event_ids = [75305]
description = "test arraySearch - conditional"
query = '''
@ -910,6 +1023,7 @@ network where mysterious_field and arraySearch(mysterious_field.subarray, s, s.a
'''
[[queries]]
name = "arraySearchWithMysteriousField5"
expected_event_ids = [75305]
description = "test arraySearch - nested"
query = '''
@ -919,6 +1033,7 @@ network where mysterious_field
'''
[[queries]]
name = "arraySearchWithMysteriousField6"
expected_event_ids = [75305]
description = "test arraySearch - nested with cross-check pass"
query = '''
@ -928,6 +1043,7 @@ network where mysterious_field
'''
[[queries]]
name = "arraySearchWithMysteriousField7"
expected_event_ids = [75305]
description = "test arraySearch - nested with cross-check pass"
query = '''
@ -937,6 +1053,7 @@ network where mysterious_field
'''
[[queries]]
name = "arraySearchWithMysteriousField8"
expected_event_ids = [75305]
description = "test arraySearch - nested with cross-check pass"
query = '''
@ -946,6 +1063,7 @@ network where mysterious_field
'''
[[queries]]
name = "safeWrapper"
expected_event_ids = []
description = "test 'safe()' wrapper for exception handling"
query = '''
@ -953,6 +1071,7 @@ network where safe(divide(process_name, process_name))
'''
[[queries]]
name = "nestedSetComparisons"
case_insensitive = true
query = '''
file where serial_event_id == 82 and (true == (process_name in ('svchost.EXE', 'bad.exe', 'bad2.exe')))
@ -961,6 +1080,7 @@ expected_event_ids = [82]
description = "nested set comparisons"
[[queries]]
name = "arrayCount1"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -968,6 +1088,7 @@ registry where arrayCount(bytes_written_string_list, s, s == '*-us') == 1
'''
[[queries]]
name = "arrayCount2"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -975,6 +1096,7 @@ registry where arrayCount(bytes_written_string_list, s, s == '*en*') == 2
'''
[[queries]]
name = "arrayContainsCaseInsensitive5"
case_insensitive = true
expected_event_ids = [57]
query = '''
@ -983,6 +1105,7 @@ registry where arrayContains(bytes_written_string_list, "missing", "en-US")
[[queries]]
name = "sequenceNonFieldBasedJoin"
note = "Sequence: non-field based join."
query = '''
sequence
@ -994,6 +1117,7 @@ expected_event_ids = [1, 2,
[[queries]]
name = "sequenceMultipleNonFieldBasedJoins"
note = "Sequence: multiple non-field based joins."
query = '''
sequence
@ -1005,6 +1129,7 @@ expected_event_ids = [1, 2,
# TODO: update toggles for this function
[[queries]]
name = "betweenCaseSensitive"
case_sensitive = true
expected_event_ids = [1, 2, 42]
query = '''
@ -1013,6 +1138,7 @@ process where between(process_name, "s", "e", false) == "t"
# TODO: add toggles to this function so it's not always insensitive
[[queries]]
name = "lengthCaseSensitive"
case_sensitive = true
expected_event_ids = [7, 14, 29, 44]
query = '''
@ -1021,6 +1147,7 @@ process where length(between(process_name, 'g', 'e')) > 0
# TODO: add toggles to this function so it's not always insensitive
#[[queries]]
#name = ""
#case_insensitive = true
#expected_event_ids = [7, 14, 22, 29, 44]
#query = '''