Related to https://github.com/elastic/elasticsearch/issues/52941
This commit is contained in:
parent
e180e2738a
commit
b47bffba24
|
@ -37,8 +37,8 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
|||
private IndicesOptions indicesOptions = IndicesOptions.fromOptions(false, false, true, false);
|
||||
|
||||
private QueryBuilder filter = null;
|
||||
private String timestampField = "timestamp";
|
||||
private String eventTypeField = "event_type";
|
||||
private String timestampField = "@timestamp";
|
||||
private String eventCategoryField = "event.category";
|
||||
private String implicitJoinKeyField = "agent.id";
|
||||
private int fetchSize = 50;
|
||||
private SearchAfterBuilder searchAfterBuilder;
|
||||
|
@ -46,7 +46,7 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
|||
|
||||
static final String KEY_FILTER = "filter";
|
||||
static final String KEY_TIMESTAMP_FIELD = "timestamp_field";
|
||||
static final String KEY_EVENT_TYPE_FIELD = "event_type_field";
|
||||
static final String KEY_EVENT_CATEGORY_FIELD = "event_category_field";
|
||||
static final String KEY_IMPLICIT_JOIN_KEY_FIELD = "implicit_join_key_field";
|
||||
static final String KEY_SIZE = "size";
|
||||
static final String KEY_SEARCH_AFTER = "search_after";
|
||||
|
@ -64,7 +64,7 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
|||
builder.field(KEY_FILTER, filter);
|
||||
}
|
||||
builder.field(KEY_TIMESTAMP_FIELD, timestampField());
|
||||
builder.field(KEY_EVENT_TYPE_FIELD, eventTypeField());
|
||||
builder.field(KEY_EVENT_CATEGORY_FIELD, eventCategoryField());
|
||||
if (implicitJoinKeyField != null) {
|
||||
builder.field(KEY_IMPLICIT_JOIN_KEY_FIELD, implicitJoinKeyField());
|
||||
}
|
||||
|
@ -107,13 +107,13 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
|||
return this;
|
||||
}
|
||||
|
||||
public String eventTypeField() {
|
||||
return this.eventTypeField;
|
||||
public String eventCategoryField() {
|
||||
return this.eventCategoryField;
|
||||
}
|
||||
|
||||
public EqlSearchRequest eventTypeField(String eventTypeField) {
|
||||
Objects.requireNonNull(eventTypeField, "event type field must not be null");
|
||||
this.eventTypeField = eventTypeField;
|
||||
public EqlSearchRequest eventCategoryField(String eventCategoryField) {
|
||||
Objects.requireNonNull(eventCategoryField, "event category field must not be null");
|
||||
this.eventCategoryField = eventCategoryField;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
|||
Objects.equals(indicesOptions, that.indicesOptions) &&
|
||||
Objects.equals(filter, that.filter) &&
|
||||
Objects.equals(timestampField, that.timestampField) &&
|
||||
Objects.equals(eventTypeField, that.eventTypeField) &&
|
||||
Objects.equals(eventCategoryField, that.eventCategoryField) &&
|
||||
Objects.equals(implicitJoinKeyField, that.implicitJoinKeyField) &&
|
||||
Objects.equals(searchAfterBuilder, that.searchAfterBuilder) &&
|
||||
Objects.equals(query, that.query);
|
||||
|
@ -194,7 +194,7 @@ public class EqlSearchRequest implements Validatable, ToXContentObject {
|
|||
filter,
|
||||
fetchSize,
|
||||
timestampField,
|
||||
eventTypeField,
|
||||
eventCategoryField,
|
||||
implicitJoinKeyField,
|
||||
searchAfterBuilder,
|
||||
query);
|
||||
|
|
|
@ -42,14 +42,16 @@ public class EqlIT extends ESRestHighLevelClientTestCase {
|
|||
public void testBasicSearch() throws Exception {
|
||||
Request doc1 = new Request(HttpPut.METHOD_NAME, "/index/_doc/1");
|
||||
doc1.setJsonEntity("{\"event_subtype_full\": \"already_running\", " +
|
||||
"\"event_type\": \"process\", " +
|
||||
"\"event\": {" +
|
||||
"\"category\": \"process\"" +
|
||||
"}," +
|
||||
"\"event_type_full\": \"process_event\", " +
|
||||
"\"opcode\": 3," +
|
||||
"\"pid\": 0," +
|
||||
"\"process_name\": \"System Idle Process\"," +
|
||||
"\"serial_event_id\": 1," +
|
||||
"\"subtype\": \"create\"," +
|
||||
"\"timestamp\": 116444736000000000," +
|
||||
"\"@timestamp\": 116444736000000000," +
|
||||
"\"unique_pid\": 1}");
|
||||
client().performRequest(doc1);
|
||||
client().performRequest(new Request(HttpPost.METHOD_NAME, "/_refresh"));
|
||||
|
@ -78,8 +80,8 @@ public class EqlIT extends ESRestHighLevelClientTestCase {
|
|||
sb.append("\"datetime" + i + "\":\"" + now + "\"");
|
||||
sb.append(",");
|
||||
}
|
||||
sb.append("\"event_type\": \"process\",");
|
||||
sb.append("\"timestamp\": \"2020-02-03T12:34:56Z\",");
|
||||
sb.append("\"event\": {\"category\": \"process\"},");
|
||||
sb.append("\"@timestamp\": \"2020-02-03T12:34:56Z\",");
|
||||
sb.append("\"serial_event_id\": 1");
|
||||
sb.append("}");
|
||||
doc1.setJsonEntity(sb.toString());
|
||||
|
|
|
@ -43,7 +43,7 @@ public class EqlSearchRequestTests extends AbstractRequestTestCase<EqlSearchRequ
|
|||
EqlSearchRequest.implicitJoinKeyField(randomAlphaOfLength(10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
EqlSearchRequest.eventTypeField(randomAlphaOfLength(10));
|
||||
EqlSearchRequest.eventCategoryField(randomAlphaOfLength(10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
EqlSearchRequest.query(randomAlphaOfLength(10));
|
||||
|
@ -72,7 +72,7 @@ public class EqlSearchRequestTests extends AbstractRequestTestCase<EqlSearchRequ
|
|||
@Override
|
||||
protected void assertInstances(org.elasticsearch.xpack.eql.action.EqlSearchRequest serverInstance, EqlSearchRequest
|
||||
clientTestInstance) {
|
||||
assertThat(serverInstance.eventTypeField(), equalTo(clientTestInstance.eventTypeField()));
|
||||
assertThat(serverInstance.eventCategoryField(), equalTo(clientTestInstance.eventCategoryField()));
|
||||
assertThat(serverInstance.implicitJoinKeyField(), equalTo(clientTestInstance.implicitJoinKeyField()));
|
||||
assertThat(serverInstance.timestampField(), equalTo(clientTestInstance.timestampField()));
|
||||
assertThat(serverInstance.filter(), equalTo(clientTestInstance.filter()));
|
||||
|
|
|
@ -35,7 +35,7 @@ specified in the `query` parameter. The EQL query matches events with an
|
|||
----
|
||||
GET sec_logs/_eql/search
|
||||
{
|
||||
"event_type_field": "event.category",
|
||||
"event_category_field": "event.category",
|
||||
"timestamp_field": "@timestamp",
|
||||
"query": """
|
||||
process where process.name == "cmd.exe"
|
||||
|
@ -89,9 +89,9 @@ The API returns the following response containing the matching event:
|
|||
[[eql-search-specify-event-type-field]]
|
||||
=== Specify an event type field
|
||||
|
||||
The EQL search API uses `event_type` as the required <<eql-required-fields,event
|
||||
type field>> by default. You can use the `event_type_field` parameter to specify
|
||||
another event type field.
|
||||
The EQL search API uses `event.category` as the required <<eql-required-fields,event
|
||||
category field>> by default. You can use the `event_category_field` parameter to specify
|
||||
another event category field.
|
||||
|
||||
For example, the following request specifies `file.type` as the event type
|
||||
field.
|
||||
|
@ -100,7 +100,7 @@ field.
|
|||
----
|
||||
GET sec_logs/_eql/search
|
||||
{
|
||||
"event_type_field": "file.type",
|
||||
"event_category_field": "file.type",
|
||||
"timestamp_field": "@timestamp",
|
||||
"query": """
|
||||
file where agent.id == "8a4f500d"
|
||||
|
@ -124,7 +124,7 @@ timestamp field.
|
|||
GET sec_logs/_eql/search
|
||||
{
|
||||
"timestamp_field": "file.accessed",
|
||||
"event_type_field": "event.category",
|
||||
"event_category_field": "event.category",
|
||||
"query": """
|
||||
file where (file.size > 1 and file.type == "file")
|
||||
"""
|
||||
|
@ -148,7 +148,7 @@ filtered documents.
|
|||
----
|
||||
GET sec_logs/_eql/search
|
||||
{
|
||||
"event_type_field": "event.category",
|
||||
"event_category_field": "event.category",
|
||||
"timestamp_field": "@timestamp",
|
||||
"filter": {
|
||||
"range" : {
|
||||
|
|
|
@ -18,7 +18,7 @@ EQL queries require an event type and a matching condition. The `where` keyword
|
|||
|
||||
[source,eql]
|
||||
----
|
||||
event_type where condition
|
||||
event.category where condition
|
||||
----
|
||||
|
||||
For example, the following EQL query matches `process` events with a `process.name`
|
||||
|
|
|
@ -46,8 +46,8 @@ public abstract class CommonEqlRestTestCase extends ESRestTestCase {
|
|||
searchValidationTests.add(new SearchTestConfiguration("{\"query\": \"\"}", 400, "query is null or empty"));
|
||||
searchValidationTests.add(new SearchTestConfiguration("{\"query\": \"" + validQuery + "\", \"timestamp_field\": \"\"}",
|
||||
400, "timestamp field is null or empty"));
|
||||
searchValidationTests.add(new SearchTestConfiguration("{\"query\": \"" + validQuery + "\", \"event_type_field\": \"\"}",
|
||||
400, "event type field is null or empty"));
|
||||
searchValidationTests.add(new SearchTestConfiguration("{\"query\": \"" + validQuery + "\", \"event_category_field\": \"\"}",
|
||||
400, "event category field is null or empty"));
|
||||
searchValidationTests.add(new SearchTestConfiguration("{\"query\": \"" + validQuery + "\", \"implicit_join_key_field\": \"\"}",
|
||||
400, "implicit join key field is null or empty"));
|
||||
searchValidationTests.add(new SearchTestConfiguration("{\"query\": \"" + validQuery + "\", \"size\": 0}",
|
||||
|
|
|
@ -7,8 +7,9 @@ setup:
|
|||
- index:
|
||||
_index: eql_test
|
||||
_id: 1
|
||||
- event_type: process
|
||||
timestamp: 2020-02-03T12:34:56Z
|
||||
- event:
|
||||
- category: process
|
||||
"@timestamp": 2020-02-03T12:34:56Z
|
||||
user: SYSTEM
|
||||
|
||||
---
|
||||
|
|
|
@ -27,9 +27,9 @@ import java.util.function.Supplier;
|
|||
|
||||
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FETCH_SIZE;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_EVENT_TYPE;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_EVENT_CATEGORY;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_TIMESTAMP;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.IMPLICIT_JOIN_KEY;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_IMPLICIT_JOIN_KEY;
|
||||
|
||||
public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Replaceable, ToXContent {
|
||||
|
||||
|
@ -39,15 +39,15 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
|
||||
private QueryBuilder filter = null;
|
||||
private String timestampField = FIELD_TIMESTAMP;
|
||||
private String eventTypeField = FIELD_EVENT_TYPE;
|
||||
private String implicitJoinKeyField = IMPLICIT_JOIN_KEY;
|
||||
private String eventCategoryField = FIELD_EVENT_CATEGORY;
|
||||
private String implicitJoinKeyField = FIELD_IMPLICIT_JOIN_KEY;
|
||||
private int fetchSize = FETCH_SIZE;
|
||||
private SearchAfterBuilder searchAfterBuilder;
|
||||
private String query;
|
||||
|
||||
static final String KEY_FILTER = "filter";
|
||||
static final String KEY_TIMESTAMP_FIELD = "timestamp_field";
|
||||
static final String KEY_EVENT_TYPE_FIELD = "event_type_field";
|
||||
static final String KEY_EVENT_CATEGORY_FIELD = "event_category_field";
|
||||
static final String KEY_IMPLICIT_JOIN_KEY_FIELD = "implicit_join_key_field";
|
||||
static final String KEY_SIZE = "size";
|
||||
static final String KEY_SEARCH_AFTER = "search_after";
|
||||
|
@ -55,7 +55,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
|
||||
static final ParseField FILTER = new ParseField(KEY_FILTER);
|
||||
static final ParseField TIMESTAMP_FIELD = new ParseField(KEY_TIMESTAMP_FIELD);
|
||||
static final ParseField EVENT_TYPE_FIELD = new ParseField(KEY_EVENT_TYPE_FIELD);
|
||||
static final ParseField EVENT_CATEGORY_FIELD = new ParseField(KEY_EVENT_CATEGORY_FIELD);
|
||||
static final ParseField IMPLICIT_JOIN_KEY_FIELD = new ParseField(KEY_IMPLICIT_JOIN_KEY_FIELD);
|
||||
static final ParseField SIZE = new ParseField(KEY_SIZE);
|
||||
static final ParseField SEARCH_AFTER = new ParseField(KEY_SEARCH_AFTER);
|
||||
|
@ -73,7 +73,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
indicesOptions = IndicesOptions.readIndicesOptions(in);
|
||||
filter = in.readOptionalNamedWriteable(QueryBuilder.class);
|
||||
timestampField = in.readString();
|
||||
eventTypeField = in.readString();
|
||||
eventCategoryField = in.readString();
|
||||
implicitJoinKeyField = in.readString();
|
||||
fetchSize = in.readVInt();
|
||||
searchAfterBuilder = in.readOptionalWriteable(SearchAfterBuilder::new);
|
||||
|
@ -104,11 +104,11 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
}
|
||||
|
||||
if (timestampField == null || timestampField.isEmpty()) {
|
||||
validationException = addValidationError("timestamp field is null or empty", validationException);
|
||||
validationException = addValidationError("@timestamp field is null or empty", validationException);
|
||||
}
|
||||
|
||||
if (eventTypeField == null || eventTypeField.isEmpty()) {
|
||||
validationException = addValidationError("event type field is null or empty", validationException);
|
||||
if (eventCategoryField == null || eventCategoryField.isEmpty()) {
|
||||
validationException = addValidationError("event category field is null or empty", validationException);
|
||||
}
|
||||
|
||||
if (implicitJoinKeyField == null || implicitJoinKeyField.isEmpty()) {
|
||||
|
@ -128,7 +128,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
builder.field(KEY_FILTER, filter);
|
||||
}
|
||||
builder.field(KEY_TIMESTAMP_FIELD, timestampField());
|
||||
builder.field(KEY_EVENT_TYPE_FIELD, eventTypeField());
|
||||
builder.field(KEY_EVENT_CATEGORY_FIELD, eventCategoryField());
|
||||
if (implicitJoinKeyField != null) {
|
||||
builder.field(KEY_IMPLICIT_JOIN_KEY_FIELD, implicitJoinKeyField());
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
parser.declareObject(EqlSearchRequest::filter,
|
||||
(p, c) -> AbstractQueryBuilder.parseInnerQueryBuilder(p), FILTER);
|
||||
parser.declareString(EqlSearchRequest::timestampField, TIMESTAMP_FIELD);
|
||||
parser.declareString(EqlSearchRequest::eventTypeField, EVENT_TYPE_FIELD);
|
||||
parser.declareString(EqlSearchRequest::eventCategoryField, EVENT_CATEGORY_FIELD);
|
||||
parser.declareString(EqlSearchRequest::implicitJoinKeyField, IMPLICIT_JOIN_KEY_FIELD);
|
||||
parser.declareInt(EqlSearchRequest::fetchSize, SIZE);
|
||||
parser.declareField(EqlSearchRequest::setSearchAfter, SearchAfterBuilder::fromXContent, SEARCH_AFTER,
|
||||
|
@ -181,10 +181,10 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
return this;
|
||||
}
|
||||
|
||||
public String eventTypeField() { return this.eventTypeField; }
|
||||
public String eventCategoryField() { return this.eventCategoryField; }
|
||||
|
||||
public EqlSearchRequest eventTypeField(String eventTypeField) {
|
||||
this.eventTypeField = eventTypeField;
|
||||
public EqlSearchRequest eventCategoryField(String eventCategoryField) {
|
||||
this.eventCategoryField = eventCategoryField;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -233,7 +233,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
indicesOptions.writeIndicesOptions(out);
|
||||
out.writeOptionalNamedWriteable(filter);
|
||||
out.writeString(timestampField);
|
||||
out.writeString(eventTypeField);
|
||||
out.writeString(eventCategoryField);
|
||||
out.writeString(implicitJoinKeyField);
|
||||
out.writeVInt(fetchSize);
|
||||
out.writeOptionalWriteable(searchAfterBuilder);
|
||||
|
@ -254,7 +254,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
Objects.equals(indicesOptions, that.indicesOptions) &&
|
||||
Objects.equals(filter, that.filter) &&
|
||||
Objects.equals(timestampField, that.timestampField) &&
|
||||
Objects.equals(eventTypeField, that.eventTypeField) &&
|
||||
Objects.equals(eventCategoryField, that.eventCategoryField) &&
|
||||
Objects.equals(implicitJoinKeyField, that.implicitJoinKeyField) &&
|
||||
Objects.equals(searchAfterBuilder, that.searchAfterBuilder) &&
|
||||
Objects.equals(query, that.query);
|
||||
|
@ -267,8 +267,7 @@ public class EqlSearchRequest extends ActionRequest implements IndicesRequest.Re
|
|||
indicesOptions,
|
||||
filter,
|
||||
fetchSize,
|
||||
timestampField,
|
||||
eventTypeField,
|
||||
timestampField, eventCategoryField,
|
||||
implicitJoinKeyField,
|
||||
searchAfterBuilder,
|
||||
query);
|
||||
|
|
|
@ -30,8 +30,8 @@ public class EqlSearchRequestBuilder extends ActionRequestBuilder<EqlSearchReque
|
|||
return this;
|
||||
}
|
||||
|
||||
public EqlSearchRequestBuilder eventTypeField(String eventTypeField) {
|
||||
request.eventTypeField(eventTypeField);
|
||||
public EqlSearchRequestBuilder eventCategoryField(String eventCategoryField) {
|
||||
request.eventCategoryField(eventCategoryField);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,9 +10,9 @@ public final class RequestDefaults {
|
|||
|
||||
private RequestDefaults() {}
|
||||
|
||||
public static final String FIELD_TIMESTAMP = "timestamp";
|
||||
public static final String FIELD_EVENT_TYPE = "event_type";
|
||||
public static final String IMPLICIT_JOIN_KEY = "agent.id";
|
||||
public static final String FIELD_TIMESTAMP = "@timestamp";
|
||||
public static final String FIELD_EVENT_CATEGORY = "event.category";
|
||||
public static final String FIELD_IMPLICIT_JOIN_KEY = "agent.id";
|
||||
|
||||
public static int FETCH_SIZE = 50;
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public abstract class LogicalPlanBuilder extends ExpressionBuilder {
|
|||
String eventName = visitIdentifier(ctx.event);
|
||||
Literal eventValue = new Literal(eventSource, eventName, DataTypes.KEYWORD);
|
||||
|
||||
UnresolvedAttribute eventField = new UnresolvedAttribute(eventSource, params.fieldEventType());
|
||||
UnresolvedAttribute eventField = new UnresolvedAttribute(eventSource, params.fieldEventCategory());
|
||||
Expression eventMatch = new Equals(eventSource, eventField, eventValue);
|
||||
|
||||
condition = new And(source, eventMatch, condition);
|
||||
|
|
|
@ -9,23 +9,23 @@ package org.elasticsearch.xpack.eql.parser;
|
|||
import java.util.List;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_EVENT_TYPE;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_EVENT_CATEGORY;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_TIMESTAMP;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.IMPLICIT_JOIN_KEY;
|
||||
import static org.elasticsearch.xpack.eql.action.RequestDefaults.FIELD_IMPLICIT_JOIN_KEY;
|
||||
|
||||
public class ParserParams {
|
||||
|
||||
private String fieldEventType = FIELD_EVENT_TYPE;
|
||||
private String fieldEventCategory = FIELD_EVENT_CATEGORY;
|
||||
private String fieldTimestamp = FIELD_TIMESTAMP;
|
||||
private String implicitJoinKey = IMPLICIT_JOIN_KEY;
|
||||
private String implicitJoinKey = FIELD_IMPLICIT_JOIN_KEY;
|
||||
private List<Object> queryParams = emptyList();
|
||||
|
||||
public String fieldEventType() {
|
||||
return fieldEventType;
|
||||
public String fieldEventCategory() {
|
||||
return fieldEventCategory;
|
||||
}
|
||||
|
||||
public ParserParams fieldEventType(String fieldEventType) {
|
||||
this.fieldEventType = fieldEventType;
|
||||
public ParserParams fieldEventCategory(String fieldEventCategory) {
|
||||
this.fieldEventCategory = fieldEventCategory;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ public class TransportEqlSearchAction extends HandledTransportAction<EqlSearchRe
|
|||
String clientId = null;
|
||||
|
||||
ParserParams params = new ParserParams()
|
||||
.fieldEventType(request.eventTypeField())
|
||||
.fieldEventCategory(request.eventCategoryField())
|
||||
.fieldTimestamp(request.timestampField())
|
||||
.implicitJoinKey(request.implicitJoinKeyField());
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.carrotsearch.randomizedtesting.annotations.ParametersFactory;
|
|||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.elasticsearch.Build;
|
||||
import org.elasticsearch.action.bulk.BulkRequestBuilder;
|
||||
import org.elasticsearch.action.bulk.BulkResponse;
|
||||
|
@ -48,6 +49,17 @@ public class EqlActionIT extends AbstractEqlIntegTestCase {
|
|||
Iterator<JsonNode> entries = rootNode.elements();
|
||||
while (entries.hasNext()) {
|
||||
JsonNode entry = entries.next();
|
||||
|
||||
// Adjust the structure of the document with additional event.category and @timestamp fields
|
||||
// Add event.category field
|
||||
ObjectNode objEvent = ((ObjectNode)entry).putObject("event");
|
||||
JsonNode objEventType = entry.get("event_type");
|
||||
objEvent.put("category", objEventType.asText());
|
||||
|
||||
// Add @timestamp field
|
||||
JsonNode objTimestamp = entry.get("timestamp");
|
||||
((ObjectNode)entry).put("@timestamp", objTimestamp.asLong());
|
||||
|
||||
bulkBuilder.add(new IndexRequest(testIndexName).source(entry.toString(), XContentType.JSON));
|
||||
}
|
||||
BulkResponse bulkResponse = bulkBuilder.setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE).get();
|
||||
|
|
|
@ -35,7 +35,7 @@ public class EqlRequestParserTests extends ESTestCase {
|
|||
EqlSearchRequest::fromXContent);
|
||||
assertParsingErrorMessage("{\"timestamp_field\" : 123}", "timestamp_field doesn't support values of type: VALUE_NUMBER",
|
||||
EqlSearchRequest::fromXContent);
|
||||
assertParsingErrorMessage("{\"event_type_field\" : 123}", "event_type_field doesn't support values of type: VALUE_NUMBER",
|
||||
assertParsingErrorMessage("{\"event_category_field\" : 123}", "event_category_field doesn't support values of type: VALUE_NUMBER",
|
||||
EqlSearchRequest::fromXContent);
|
||||
assertParsingErrorMessage("{\"implicit_join_key_field\" : 123}",
|
||||
"implicit_join_key_field doesn't support values of type: VALUE_NUMBER",
|
||||
|
@ -51,7 +51,7 @@ public class EqlRequestParserTests extends ESTestCase {
|
|||
|
||||
EqlSearchRequest request = generateRequest("endgame-*", "{\"filter\" : {\"match\" : {\"foo\":\"bar\"}}, "
|
||||
+ "\"timestamp_field\" : \"tsf\", "
|
||||
+ "\"event_type_field\" : \"etf\","
|
||||
+ "\"event_category_field\" : \"etf\","
|
||||
+ "\"implicit_join_key_field\" : \"imjf\","
|
||||
+ "\"search_after\" : [ 12345678, \"device-20184\", \"/user/local/foo.exe\", \"2019-11-26T00:45:43.542\" ],"
|
||||
+ "\"size\" : \"101\","
|
||||
|
@ -64,7 +64,7 @@ public class EqlRequestParserTests extends ESTestCase {
|
|||
assertEquals("foo", filter.fieldName());
|
||||
assertEquals("bar", filter.value());
|
||||
assertEquals("tsf", request.timestampField());
|
||||
assertEquals("etf", request.eventTypeField());
|
||||
assertEquals("etf", request.eventCategoryField());
|
||||
assertEquals("imjf", request.implicitJoinKeyField());
|
||||
assertArrayEquals(new Object[]{12345678, "device-20184", "/user/local/foo.exe", "2019-11-26T00:45:43.542"}, request.searchAfter());
|
||||
assertEquals(101, request.fetchSize());
|
||||
|
|
|
@ -64,7 +64,7 @@ public class EqlSearchRequestTests extends AbstractSerializingTestCase<EqlSearch
|
|||
.indices(new String[]{defaultTestIndex})
|
||||
.filter(filter)
|
||||
.timestampField(randomAlphaOfLength(10))
|
||||
.eventTypeField(randomAlphaOfLength(10))
|
||||
.eventCategoryField(randomAlphaOfLength(10))
|
||||
.implicitJoinKeyField(randomAlphaOfLength(10))
|
||||
.fetchSize(randomIntBetween(1, 50))
|
||||
.query(randomAlphaOfLength(10));
|
||||
|
|
|
@ -204,10 +204,10 @@ public class VerifierTests extends ESTestCase {
|
|||
accept("file where serial_event_id % 40 == 2");
|
||||
}
|
||||
|
||||
// Test mapping that doesn't have property event_type defined
|
||||
public void testMissingEventType() {
|
||||
final IndexResolution idxr = loadIndexResolution("mapping-missing-event-type.json");
|
||||
assertEquals("1:1: Unknown column [event_type]", error(idxr, "foo where true"));
|
||||
// Test mapping that doesn't have property event.category defined
|
||||
public void testMissingEventCategory() {
|
||||
final IndexResolution idxr = loadIndexResolution("mapping-missing-event-category.json");
|
||||
assertEquals("1:1: Unknown column [event.category]", error(idxr, "foo where true"));
|
||||
}
|
||||
|
||||
public void testAliasErrors() {
|
||||
|
|
|
@ -30,21 +30,21 @@ public class LogicalPlanTests extends ESTestCase {
|
|||
|
||||
public void testEventQuery() {
|
||||
LogicalPlan fullQuery = parser.createStatement("process where process_name == 'net.exe'");
|
||||
Expression fullExpression = expr("event_type == 'process' and process_name == 'net.exe'");
|
||||
Expression fullExpression = expr("event.category == 'process' and process_name == 'net.exe'");
|
||||
|
||||
LogicalPlan filter = new Filter(Source.EMPTY, new UnresolvedRelation(Source.EMPTY, null, "", false, ""), fullExpression);
|
||||
Order order = new Order(Source.EMPTY, new UnresolvedAttribute(Source.EMPTY, "timestamp"), OrderDirection.ASC, NullsPosition.FIRST);
|
||||
Order order = new Order(Source.EMPTY, new UnresolvedAttribute(Source.EMPTY, "@timestamp"), OrderDirection.ASC, NullsPosition.FIRST);
|
||||
LogicalPlan expected = new OrderBy(Source.EMPTY, filter, singletonList(order));
|
||||
assertEquals(expected, fullQuery);
|
||||
}
|
||||
|
||||
public void testParameterizedEventQuery() {
|
||||
ParserParams params = new ParserParams().fieldEventType("myCustomEvent");
|
||||
ParserParams params = new ParserParams().fieldEventCategory("myCustomEvent");
|
||||
LogicalPlan fullQuery = parser.createStatement("process where process_name == 'net.exe'", params);
|
||||
Expression fullExpression = expr("myCustomEvent == 'process' and process_name == 'net.exe'");
|
||||
|
||||
LogicalPlan filter = new Filter(Source.EMPTY, new UnresolvedRelation(Source.EMPTY, null, "", false, ""), fullExpression);
|
||||
Order order = new Order(Source.EMPTY, new UnresolvedAttribute(Source.EMPTY, "timestamp"), OrderDirection.ASC, NullsPosition.FIRST);
|
||||
Order order = new Order(Source.EMPTY, new UnresolvedAttribute(Source.EMPTY, "@timestamp"), OrderDirection.ASC, NullsPosition.FIRST);
|
||||
LogicalPlan expected = new OrderBy(Source.EMPTY, filter, singletonList(order));
|
||||
assertEquals(expected, fullQuery);
|
||||
}
|
||||
|
|
|
@ -45,11 +45,11 @@ public class QueryFolderTests extends ESTestCase {
|
|||
PhysicalPlan p = plan("process where true");
|
||||
assertEquals(EsQueryExec.class, p.getClass());
|
||||
EsQueryExec eqe = (EsQueryExec) p;
|
||||
assertEquals(22, eqe.output().size());
|
||||
assertEquals(23, eqe.output().size());
|
||||
assertEquals(KEYWORD, eqe.output().get(0).dataType());
|
||||
String query = eqe.queryContainer().toString().replaceAll("\\s+", "");
|
||||
// test query term
|
||||
assertThat(query, containsString("\"term\":{\"event_type\":{\"value\":\"process\""));
|
||||
assertThat(query, containsString("\"term\":{\"event.category\":{\"value\":\"process\""));
|
||||
// test field source extraction
|
||||
assertThat(query, containsString("\"_source\":{\"includes\":[],\"excludes\":[]"));
|
||||
}
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"user_name" : {
|
||||
"type" : "keyword"
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"blob" : {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"boolean_field" : {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"date" : {
|
||||
|
|
|
@ -3,8 +3,12 @@
|
|||
"command_line" : {
|
||||
"type" : "keyword"
|
||||
},
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"md5" : {
|
||||
"type" : "keyword"
|
||||
|
@ -30,7 +34,7 @@
|
|||
"subtype" : {
|
||||
"type" : "keyword"
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"user" : {
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"location" : {
|
||||
"type" : "geo_point"
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"ip_addr" : {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"serial_event_id" : {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"multi_field" : {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"processes" : {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"description_nodoc" : {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"long_field" : {
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"timestamp" : {
|
||||
"@timestamp" : {
|
||||
"type" : "date"
|
||||
},
|
||||
"endgame" : {
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
{
|
||||
"properties" : {
|
||||
"event_type" : {
|
||||
"event" : {
|
||||
"properties" : {
|
||||
"category" : {
|
||||
"type" : "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"integer_range_field" : {
|
||||
"type" : "integer_range"
|
||||
|
|
Loading…
Reference in New Issue