mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[Security Solution] add api validation for event filters (#123776)
This commit is contained in:
parent
258039a919
commit
fa38d1ae0d
12 changed files with 742 additions and 340 deletions
|
@ -10,7 +10,10 @@ import type {
|
|||
CreateExceptionListItemSchema,
|
||||
UpdateExceptionListItemSchema,
|
||||
} from '@kbn/securitysolution-io-ts-list-types';
|
||||
import { ENDPOINT_TRUSTED_APPS_LIST_ID } from '@kbn/securitysolution-list-constants';
|
||||
import {
|
||||
ENDPOINT_EVENT_FILTERS_LIST_ID,
|
||||
ENDPOINT_TRUSTED_APPS_LIST_ID,
|
||||
} from '@kbn/securitysolution-list-constants';
|
||||
import { BaseDataGenerator } from './base_data_generator';
|
||||
import { ConditionEntryField } from '../types';
|
||||
import { BY_POLICY_ARTIFACT_TAG_PREFIX } from '../service/artifacts/constants';
|
||||
|
@ -198,4 +201,84 @@ export class ExceptionsListItemGenerator extends BaseDataGenerator<ExceptionList
|
|||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
generateEventFilter(overrides: Partial<ExceptionListItemSchema> = {}): ExceptionListItemSchema {
|
||||
const eventFilter = this.generate(overrides);
|
||||
|
||||
return {
|
||||
...eventFilter,
|
||||
name: `Event filter (${this.randomString(5)})`,
|
||||
list_id: ENDPOINT_EVENT_FILTERS_LIST_ID,
|
||||
};
|
||||
}
|
||||
|
||||
generateEventFilterForCreate(
|
||||
overrides: Partial<CreateExceptionListItemSchema> = {}
|
||||
): CreateExceptionListItemSchemaWithNonNullProps {
|
||||
const {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
description,
|
||||
entries,
|
||||
list_id,
|
||||
name,
|
||||
type,
|
||||
comments,
|
||||
item_id,
|
||||
meta,
|
||||
namespace_type,
|
||||
os_types,
|
||||
tags,
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
} = this.generateEventFilter();
|
||||
return {
|
||||
description,
|
||||
entries,
|
||||
list_id,
|
||||
name,
|
||||
type,
|
||||
comments,
|
||||
item_id,
|
||||
meta,
|
||||
namespace_type,
|
||||
os_types,
|
||||
tags,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
generateEventFilterForUpdate(
|
||||
overrides: Partial<UpdateExceptionListItemSchema> = {}
|
||||
): UpdateExceptionListItemSchemaWithNonNullProps {
|
||||
const {
|
||||
/* eslint-disable @typescript-eslint/naming-convention */
|
||||
description,
|
||||
entries,
|
||||
name,
|
||||
type,
|
||||
comments,
|
||||
id,
|
||||
item_id,
|
||||
meta,
|
||||
namespace_type,
|
||||
os_types,
|
||||
tags,
|
||||
_version,
|
||||
/* eslint-enable @typescript-eslint/naming-convention */
|
||||
} = this.generateEventFilter();
|
||||
return {
|
||||
description,
|
||||
entries,
|
||||
name,
|
||||
type,
|
||||
comments,
|
||||
id,
|
||||
item_id,
|
||||
meta,
|
||||
namespace_type,
|
||||
os_types,
|
||||
tags,
|
||||
_version: _version ?? 'some value',
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,339 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
export const EXCEPTIONABLE_ENDPOINT_EVENT_FIELDS = [
|
||||
'@timestamp',
|
||||
'agent.id',
|
||||
'agent.name',
|
||||
'agent.type',
|
||||
'agent.version',
|
||||
'data_stream.dataset',
|
||||
'data_stream.namespace',
|
||||
'data_stream.type',
|
||||
'destination.address',
|
||||
'destination.bytes',
|
||||
'destination.domain',
|
||||
'destination.geo.city_name',
|
||||
'destination.geo.continent_name',
|
||||
'destination.geo.country_iso_code',
|
||||
'destination.geo.country_name',
|
||||
'destination.geo.location',
|
||||
'destination.geo.name',
|
||||
'destination.geo.region_iso_code',
|
||||
'destination.geo.region_name',
|
||||
'destination.ip',
|
||||
'destination.packets',
|
||||
'destination.port',
|
||||
'destination.registered_domain',
|
||||
'destination.top_level_domain',
|
||||
'dll.code_signature.exists',
|
||||
'dll.code_signature.status',
|
||||
'dll.code_signature.subject_name',
|
||||
'dll.code_signature.trusted',
|
||||
'dll.code_signature.valid',
|
||||
'dll.Ext',
|
||||
'dll.Ext.code_signature',
|
||||
'dll.Ext.code_signature.exists',
|
||||
'dll.Ext.code_signature.status',
|
||||
'dll.Ext.code_signature.subject_name',
|
||||
'dll.Ext.code_signature.trusted',
|
||||
'dll.Ext.code_signature.valid',
|
||||
'dll.Ext.load_index',
|
||||
'dll.hash.md5',
|
||||
'dll.hash.sha1',
|
||||
'dll.hash.sha256',
|
||||
'dll.hash.sha512',
|
||||
'dll.name',
|
||||
'dll.path',
|
||||
'dll.pe.company',
|
||||
'dll.pe.description',
|
||||
'dll.pe.file_version',
|
||||
'dll.pe.imphash',
|
||||
'dll.pe.original_file_name',
|
||||
'dll.pe.product',
|
||||
'dns.Ext',
|
||||
'dns.Ext.options',
|
||||
'dns.Ext.status',
|
||||
'dns.question.name',
|
||||
'dns.question.registered_domain',
|
||||
'dns.question.subdomain',
|
||||
'dns.question.top_level_domain',
|
||||
'dns.question.type',
|
||||
'dns.resolved_ip',
|
||||
'ecs.version',
|
||||
'elastic.agent',
|
||||
'elastic.agent.id',
|
||||
'Endpoint.policy',
|
||||
'Endpoint.policy.applied',
|
||||
'Endpoint.policy.applied.id',
|
||||
'Endpoint.policy.applied.name',
|
||||
'Endpoint.policy.applied.status',
|
||||
'Endpoint.status',
|
||||
'event.action',
|
||||
'event.category',
|
||||
'event.code',
|
||||
'event.created',
|
||||
'event.dataset',
|
||||
'event.Ext',
|
||||
'event.Ext.correlation',
|
||||
'event.Ext.correlation.id',
|
||||
'event.hash',
|
||||
'event.id',
|
||||
'event.ingested',
|
||||
'event.module',
|
||||
'event.outcome',
|
||||
'event.provider',
|
||||
'event.sequence',
|
||||
'event.severity',
|
||||
'event.type',
|
||||
'file.accessed',
|
||||
'file.attributes',
|
||||
'file.created',
|
||||
'file.ctime',
|
||||
'file.device',
|
||||
'file.directory',
|
||||
'file.drive_letter',
|
||||
'file.Ext',
|
||||
'file.Ext.code_signature',
|
||||
'file.Ext.code_signature.exists',
|
||||
'file.Ext.code_signature.status',
|
||||
'file.Ext.code_signature.subject_name',
|
||||
'file.Ext.code_signature.trusted',
|
||||
'file.Ext.code_signature.valid',
|
||||
'file.Ext.entropy',
|
||||
'file.Ext.header_data',
|
||||
'file.Ext.monotonic_id',
|
||||
'file.Ext.original',
|
||||
'file.Ext.original.gid',
|
||||
'file.Ext.original.group',
|
||||
'file.Ext.original.mode',
|
||||
'file.Ext.original.name',
|
||||
'file.Ext.original.owner',
|
||||
'file.Ext.original.path',
|
||||
'file.Ext.original.uid',
|
||||
'file.Ext.windows',
|
||||
'file.Ext.windows.zone_identifier',
|
||||
'file.extension',
|
||||
'file.gid',
|
||||
'file.group',
|
||||
'file.hash.md5',
|
||||
'file.hash.sha1',
|
||||
'file.hash.sha256',
|
||||
'file.hash.sha512',
|
||||
'file.inode',
|
||||
'file.mime_type',
|
||||
'file.mode',
|
||||
'file.mtime',
|
||||
'file.name',
|
||||
'file.owner',
|
||||
'file.path',
|
||||
'file.path.caseless',
|
||||
'file.path.text',
|
||||
'file.pe.company',
|
||||
'file.pe.description',
|
||||
'file.pe.file_version',
|
||||
'file.pe.imphash',
|
||||
'file.pe.original_file_name',
|
||||
'file.pe.product',
|
||||
'file.size',
|
||||
'file.target_path',
|
||||
'file.target_path.caseless',
|
||||
'file.target_path.text',
|
||||
'file.type',
|
||||
'file.uid',
|
||||
'group.domain',
|
||||
'group.Ext',
|
||||
'group.Ext.real',
|
||||
'group.Ext.real.id',
|
||||
'group.Ext.real.name',
|
||||
'group.id',
|
||||
'group.name',
|
||||
'host.architecture',
|
||||
'host.domain',
|
||||
'host.hostname',
|
||||
'host.id',
|
||||
'host.ip',
|
||||
'host.mac',
|
||||
'host.name',
|
||||
'host.os.Ext',
|
||||
'host.os.Ext.variant',
|
||||
'host.os.family',
|
||||
'host.os.full',
|
||||
'host.os.full.caseless',
|
||||
'host.os.full.text',
|
||||
'host.os.kernel',
|
||||
'host.os.name',
|
||||
'host.os.name.caseless',
|
||||
'host.os.name.text',
|
||||
'host.os.platform',
|
||||
'host.os.version',
|
||||
'host.type',
|
||||
'host.uptime',
|
||||
'http.request.body.bytes',
|
||||
'http.request.body.content',
|
||||
'http.request.body.content.text',
|
||||
'http.request.bytes',
|
||||
'http.response.body.bytes',
|
||||
'http.response.body.content',
|
||||
'http.response.body.content.text',
|
||||
'http.response.bytes',
|
||||
'http.response.Ext',
|
||||
'http.response.Ext.version',
|
||||
'http.response.status_code',
|
||||
'message',
|
||||
'network.bytes',
|
||||
'network.community_id',
|
||||
'network.direction',
|
||||
'network.iana_number',
|
||||
'network.packets',
|
||||
'network.protocol',
|
||||
'network.transport',
|
||||
'network.type',
|
||||
'package.name',
|
||||
'process.args',
|
||||
'process.args_count',
|
||||
'process.code_signature.exists',
|
||||
'process.code_signature.status',
|
||||
'process.code_signature.subject_name',
|
||||
'process.code_signature.trusted',
|
||||
'process.code_signature.valid',
|
||||
'process.command_line',
|
||||
'process.command_line.caseless',
|
||||
'process.command_line.text',
|
||||
'process.entity_id',
|
||||
'process.executable',
|
||||
'process.executable.caseless',
|
||||
'process.executable.text',
|
||||
'process.exit_code',
|
||||
'process.Ext',
|
||||
'process.Ext.ancestry',
|
||||
'process.Ext.authentication_id',
|
||||
'process.Ext.code_signature',
|
||||
'process.Ext.code_signature.exists',
|
||||
'process.Ext.code_signature.status',
|
||||
'process.Ext.code_signature.subject_name',
|
||||
'process.Ext.code_signature.trusted',
|
||||
'process.Ext.code_signature.valid',
|
||||
'process.Ext.defense_evasions',
|
||||
'process.Ext.session',
|
||||
'process.Ext.token.elevation',
|
||||
'process.Ext.token.elevation_type',
|
||||
'process.Ext.token.integrity_level_name',
|
||||
'process.hash.md5',
|
||||
'process.hash.sha1',
|
||||
'process.hash.sha256',
|
||||
'process.hash.sha512',
|
||||
'process.name',
|
||||
'process.name.caseless',
|
||||
'process.name.text',
|
||||
'process.parent.args',
|
||||
'process.parent.args_count',
|
||||
'process.parent.code_signature.exists',
|
||||
'process.parent.code_signature.status',
|
||||
'process.parent.code_signature.subject_name',
|
||||
'process.parent.code_signature.trusted',
|
||||
'process.parent.code_signature.valid',
|
||||
'process.parent.command_line',
|
||||
'process.parent.command_line.caseless',
|
||||
'process.parent.command_line.text',
|
||||
'process.parent.entity_id',
|
||||
'process.parent.executable',
|
||||
'process.parent.executable.caseless',
|
||||
'process.parent.executable.text',
|
||||
'process.parent.exit_code',
|
||||
'process.parent.Ext',
|
||||
'process.parent.Ext.code_signature',
|
||||
'process.parent.Ext.code_signature.exists',
|
||||
'process.parent.Ext.code_signature.status',
|
||||
'process.parent.Ext.code_signature.subject_name',
|
||||
'process.parent.Ext.code_signature.trusted',
|
||||
'process.parent.Ext.code_signature.valid',
|
||||
'process.parent.Ext.real',
|
||||
'process.parent.Ext.real.pid',
|
||||
'process.parent.hash.md5',
|
||||
'process.parent.hash.sha1',
|
||||
'process.parent.hash.sha256',
|
||||
'process.parent.hash.sha512',
|
||||
'process.parent.name',
|
||||
'process.parent.name.caseless',
|
||||
'process.parent.name.text',
|
||||
'process.parent.pe.company',
|
||||
'process.parent.pe.description',
|
||||
'process.parent.pe.file_version',
|
||||
'process.parent.pe.imphash',
|
||||
'process.parent.pe.original_file_name',
|
||||
'process.parent.pe.product',
|
||||
'process.parent.pgid',
|
||||
'process.parent.pid',
|
||||
'process.parent.ppid',
|
||||
'process.parent.thread.id',
|
||||
'process.parent.thread.name',
|
||||
'process.parent.title',
|
||||
'process.parent.title.text',
|
||||
'process.parent.uptime',
|
||||
'process.parent.working_directory',
|
||||
'process.parent.working_directory.caseless',
|
||||
'process.parent.working_directory.text',
|
||||
'process.pe.company',
|
||||
'process.pe.description',
|
||||
'process.pe.file_version',
|
||||
'process.pe.imphash',
|
||||
'process.pe.original_file_name',
|
||||
'process.pe.product',
|
||||
'process.pgid',
|
||||
'process.pid',
|
||||
'process.ppid',
|
||||
'process.thread.id',
|
||||
'process.thread.name',
|
||||
'process.title',
|
||||
'process.title.text',
|
||||
'process.uptime',
|
||||
'process.working_directory',
|
||||
'process.working_directory.caseless',
|
||||
'process.working_directory.text',
|
||||
'registry.data.bytes',
|
||||
'registry.data.strings',
|
||||
'registry.hive',
|
||||
'registry.key',
|
||||
'registry.path',
|
||||
'registry.value',
|
||||
'source.address',
|
||||
'source.bytes',
|
||||
'source.domain',
|
||||
'source.geo.city_name',
|
||||
'source.geo.continent_name',
|
||||
'source.geo.country_iso_code',
|
||||
'source.geo.country_name',
|
||||
'source.geo.location',
|
||||
'source.geo.name',
|
||||
'source.geo.region_iso_code',
|
||||
'source.geo.region_name',
|
||||
'source.ip',
|
||||
'source.packets',
|
||||
'source.port',
|
||||
'source.registered_domain',
|
||||
'source.top_level_domain',
|
||||
'user.domain',
|
||||
'user.email',
|
||||
'user.Ext',
|
||||
'user.Ext.real',
|
||||
'user.Ext.real.id',
|
||||
'user.Ext.real.name',
|
||||
'user.full_name',
|
||||
'user.full_name.text',
|
||||
'user.group.domain',
|
||||
'user.group.Ext',
|
||||
'user.group.Ext.real',
|
||||
'user.group.Ext.real.id',
|
||||
'user.group.Ext.real.name',
|
||||
'user.group.id',
|
||||
'user.group.name',
|
||||
'user.hash',
|
||||
'user.id',
|
||||
'user.name',
|
||||
'user.name.text',
|
||||
];
|
|
@ -1,332 +0,0 @@
|
|||
[
|
||||
"@timestamp",
|
||||
"agent.id",
|
||||
"agent.name",
|
||||
"agent.type",
|
||||
"agent.version",
|
||||
"data_stream.dataset",
|
||||
"data_stream.namespace",
|
||||
"data_stream.type",
|
||||
"destination.address",
|
||||
"destination.bytes",
|
||||
"destination.domain",
|
||||
"destination.geo.city_name",
|
||||
"destination.geo.continent_name",
|
||||
"destination.geo.country_iso_code",
|
||||
"destination.geo.country_name",
|
||||
"destination.geo.location",
|
||||
"destination.geo.name",
|
||||
"destination.geo.region_iso_code",
|
||||
"destination.geo.region_name",
|
||||
"destination.ip",
|
||||
"destination.packets",
|
||||
"destination.port",
|
||||
"destination.registered_domain",
|
||||
"destination.top_level_domain",
|
||||
"dll.code_signature.exists",
|
||||
"dll.code_signature.status",
|
||||
"dll.code_signature.subject_name",
|
||||
"dll.code_signature.trusted",
|
||||
"dll.code_signature.valid",
|
||||
"dll.Ext",
|
||||
"dll.Ext.code_signature",
|
||||
"dll.Ext.code_signature.exists",
|
||||
"dll.Ext.code_signature.status",
|
||||
"dll.Ext.code_signature.subject_name",
|
||||
"dll.Ext.code_signature.trusted",
|
||||
"dll.Ext.code_signature.valid",
|
||||
"dll.Ext.load_index",
|
||||
"dll.hash.md5",
|
||||
"dll.hash.sha1",
|
||||
"dll.hash.sha256",
|
||||
"dll.hash.sha512",
|
||||
"dll.name",
|
||||
"dll.path",
|
||||
"dll.pe.company",
|
||||
"dll.pe.description",
|
||||
"dll.pe.file_version",
|
||||
"dll.pe.imphash",
|
||||
"dll.pe.original_file_name",
|
||||
"dll.pe.product",
|
||||
"dns.Ext",
|
||||
"dns.Ext.options",
|
||||
"dns.Ext.status",
|
||||
"dns.question.name",
|
||||
"dns.question.registered_domain",
|
||||
"dns.question.subdomain",
|
||||
"dns.question.top_level_domain",
|
||||
"dns.question.type",
|
||||
"dns.resolved_ip",
|
||||
"ecs.version",
|
||||
"elastic.agent",
|
||||
"elastic.agent.id",
|
||||
"Endpoint.policy",
|
||||
"Endpoint.policy.applied",
|
||||
"Endpoint.policy.applied.id",
|
||||
"Endpoint.policy.applied.name",
|
||||
"Endpoint.policy.applied.status",
|
||||
"Endpoint.status",
|
||||
"event.action",
|
||||
"event.category",
|
||||
"event.code",
|
||||
"event.created",
|
||||
"event.dataset",
|
||||
"event.Ext",
|
||||
"event.Ext.correlation",
|
||||
"event.Ext.correlation.id",
|
||||
"event.hash",
|
||||
"event.id",
|
||||
"event.ingested",
|
||||
"event.module",
|
||||
"event.outcome",
|
||||
"event.provider",
|
||||
"event.sequence",
|
||||
"event.severity",
|
||||
"event.type",
|
||||
"file.accessed",
|
||||
"file.attributes",
|
||||
"file.created",
|
||||
"file.ctime",
|
||||
"file.device",
|
||||
"file.directory",
|
||||
"file.drive_letter",
|
||||
"file.Ext",
|
||||
"file.Ext.code_signature",
|
||||
"file.Ext.code_signature.exists",
|
||||
"file.Ext.code_signature.status",
|
||||
"file.Ext.code_signature.subject_name",
|
||||
"file.Ext.code_signature.trusted",
|
||||
"file.Ext.code_signature.valid",
|
||||
"file.Ext.entropy",
|
||||
"file.Ext.header_data",
|
||||
"file.Ext.monotonic_id",
|
||||
"file.Ext.original",
|
||||
"file.Ext.original.gid",
|
||||
"file.Ext.original.group",
|
||||
"file.Ext.original.mode",
|
||||
"file.Ext.original.name",
|
||||
"file.Ext.original.owner",
|
||||
"file.Ext.original.path",
|
||||
"file.Ext.original.uid",
|
||||
"file.Ext.windows",
|
||||
"file.Ext.windows.zone_identifier",
|
||||
"file.extension",
|
||||
"file.gid",
|
||||
"file.group",
|
||||
"file.hash.md5",
|
||||
"file.hash.sha1",
|
||||
"file.hash.sha256",
|
||||
"file.hash.sha512",
|
||||
"file.inode",
|
||||
"file.mime_type",
|
||||
"file.mode",
|
||||
"file.mtime",
|
||||
"file.name",
|
||||
"file.owner",
|
||||
"file.path",
|
||||
"file.path.caseless",
|
||||
"file.path.text",
|
||||
"file.pe.company",
|
||||
"file.pe.description",
|
||||
"file.pe.file_version",
|
||||
"file.pe.imphash",
|
||||
"file.pe.original_file_name",
|
||||
"file.pe.product",
|
||||
"file.size",
|
||||
"file.target_path",
|
||||
"file.target_path.caseless",
|
||||
"file.target_path.text",
|
||||
"file.type",
|
||||
"file.uid",
|
||||
"group.domain",
|
||||
"group.Ext",
|
||||
"group.Ext.real",
|
||||
"group.Ext.real.id",
|
||||
"group.Ext.real.name",
|
||||
"group.id",
|
||||
"group.name",
|
||||
"host.architecture",
|
||||
"host.domain",
|
||||
"host.hostname",
|
||||
"host.id",
|
||||
"host.ip",
|
||||
"host.mac",
|
||||
"host.name",
|
||||
"host.os.Ext",
|
||||
"host.os.Ext.variant",
|
||||
"host.os.family",
|
||||
"host.os.full",
|
||||
"host.os.full.caseless",
|
||||
"host.os.full.text",
|
||||
"host.os.kernel",
|
||||
"host.os.name",
|
||||
"host.os.name.caseless",
|
||||
"host.os.name.text",
|
||||
"host.os.platform",
|
||||
"host.os.version",
|
||||
"host.type",
|
||||
"host.uptime",
|
||||
"http.request.body.bytes",
|
||||
"http.request.body.content",
|
||||
"http.request.body.content.text",
|
||||
"http.request.bytes",
|
||||
"http.response.body.bytes",
|
||||
"http.response.body.content",
|
||||
"http.response.body.content.text",
|
||||
"http.response.bytes",
|
||||
"http.response.Ext",
|
||||
"http.response.Ext.version",
|
||||
"http.response.status_code",
|
||||
"message",
|
||||
"network.bytes",
|
||||
"network.community_id",
|
||||
"network.direction",
|
||||
"network.iana_number",
|
||||
"network.packets",
|
||||
"network.protocol",
|
||||
"network.transport",
|
||||
"network.type",
|
||||
"package.name",
|
||||
"process.args",
|
||||
"process.args_count",
|
||||
"process.code_signature.exists",
|
||||
"process.code_signature.status",
|
||||
"process.code_signature.subject_name",
|
||||
"process.code_signature.trusted",
|
||||
"process.code_signature.valid",
|
||||
"process.command_line",
|
||||
"process.command_line.caseless",
|
||||
"process.command_line.text",
|
||||
"process.entity_id",
|
||||
"process.executable",
|
||||
"process.executable.caseless",
|
||||
"process.executable.text",
|
||||
"process.exit_code",
|
||||
"process.Ext",
|
||||
"process.Ext.ancestry",
|
||||
"process.Ext.authentication_id",
|
||||
"process.Ext.code_signature",
|
||||
"process.Ext.code_signature.exists",
|
||||
"process.Ext.code_signature.status",
|
||||
"process.Ext.code_signature.subject_name",
|
||||
"process.Ext.code_signature.trusted",
|
||||
"process.Ext.code_signature.valid",
|
||||
"process.Ext.defense_evasions",
|
||||
"process.Ext.session",
|
||||
"process.Ext.token.elevation",
|
||||
"process.Ext.token.elevation_type",
|
||||
"process.Ext.token.integrity_level_name",
|
||||
"process.hash.md5",
|
||||
"process.hash.sha1",
|
||||
"process.hash.sha256",
|
||||
"process.hash.sha512",
|
||||
"process.name",
|
||||
"process.name.caseless",
|
||||
"process.name.text",
|
||||
"process.parent.args",
|
||||
"process.parent.args_count",
|
||||
"process.parent.code_signature.exists",
|
||||
"process.parent.code_signature.status",
|
||||
"process.parent.code_signature.subject_name",
|
||||
"process.parent.code_signature.trusted",
|
||||
"process.parent.code_signature.valid",
|
||||
"process.parent.command_line",
|
||||
"process.parent.command_line.caseless",
|
||||
"process.parent.command_line.text",
|
||||
"process.parent.entity_id",
|
||||
"process.parent.executable",
|
||||
"process.parent.executable.caseless",
|
||||
"process.parent.executable.text",
|
||||
"process.parent.exit_code",
|
||||
"process.parent.Ext",
|
||||
"process.parent.Ext.code_signature",
|
||||
"process.parent.Ext.code_signature.exists",
|
||||
"process.parent.Ext.code_signature.status",
|
||||
"process.parent.Ext.code_signature.subject_name",
|
||||
"process.parent.Ext.code_signature.trusted",
|
||||
"process.parent.Ext.code_signature.valid",
|
||||
"process.parent.Ext.real",
|
||||
"process.parent.Ext.real.pid",
|
||||
"process.parent.hash.md5",
|
||||
"process.parent.hash.sha1",
|
||||
"process.parent.hash.sha256",
|
||||
"process.parent.hash.sha512",
|
||||
"process.parent.name",
|
||||
"process.parent.name.caseless",
|
||||
"process.parent.name.text",
|
||||
"process.parent.pe.company",
|
||||
"process.parent.pe.description",
|
||||
"process.parent.pe.file_version",
|
||||
"process.parent.pe.imphash",
|
||||
"process.parent.pe.original_file_name",
|
||||
"process.parent.pe.product",
|
||||
"process.parent.pgid",
|
||||
"process.parent.pid",
|
||||
"process.parent.ppid",
|
||||
"process.parent.thread.id",
|
||||
"process.parent.thread.name",
|
||||
"process.parent.title",
|
||||
"process.parent.title.text",
|
||||
"process.parent.uptime",
|
||||
"process.parent.working_directory",
|
||||
"process.parent.working_directory.caseless",
|
||||
"process.parent.working_directory.text",
|
||||
"process.pe.company",
|
||||
"process.pe.description",
|
||||
"process.pe.file_version",
|
||||
"process.pe.imphash",
|
||||
"process.pe.original_file_name",
|
||||
"process.pe.product",
|
||||
"process.pgid",
|
||||
"process.pid",
|
||||
"process.ppid",
|
||||
"process.thread.id",
|
||||
"process.thread.name",
|
||||
"process.title",
|
||||
"process.title.text",
|
||||
"process.uptime",
|
||||
"process.working_directory",
|
||||
"process.working_directory.caseless",
|
||||
"process.working_directory.text",
|
||||
"registry.data.bytes",
|
||||
"registry.data.strings",
|
||||
"registry.hive",
|
||||
"registry.key",
|
||||
"registry.path",
|
||||
"registry.value",
|
||||
"source.address",
|
||||
"source.bytes",
|
||||
"source.domain",
|
||||
"source.geo.city_name",
|
||||
"source.geo.continent_name",
|
||||
"source.geo.country_iso_code",
|
||||
"source.geo.country_name",
|
||||
"source.geo.location",
|
||||
"source.geo.name",
|
||||
"source.geo.region_iso_code",
|
||||
"source.geo.region_name",
|
||||
"source.ip",
|
||||
"source.packets",
|
||||
"source.port",
|
||||
"source.registered_domain",
|
||||
"source.top_level_domain",
|
||||
"user.domain",
|
||||
"user.email",
|
||||
"user.Ext",
|
||||
"user.Ext.real",
|
||||
"user.Ext.real.id",
|
||||
"user.Ext.real.name",
|
||||
"user.full_name",
|
||||
"user.full_name.text",
|
||||
"user.group.domain",
|
||||
"user.group.Ext",
|
||||
"user.group.Ext.real",
|
||||
"user.group.Ext.real.id",
|
||||
"user.group.Ext.real.name",
|
||||
"user.group.id",
|
||||
"user.group.name",
|
||||
"user.hash",
|
||||
"user.id",
|
||||
"user.name",
|
||||
"user.name.text"
|
||||
]
|
|
@ -43,7 +43,7 @@ import { WithCopyToClipboard } from '../../lib/clipboard/with_copy_to_clipboard'
|
|||
import exceptionableLinuxFields from './exceptionable_linux_fields.json';
|
||||
import exceptionableWindowsMacFields from './exceptionable_windows_mac_fields.json';
|
||||
import exceptionableEndpointFields from './exceptionable_endpoint_fields.json';
|
||||
import exceptionableEndpointEventFields from './exceptionable_endpoint_event_fields.json';
|
||||
import { EXCEPTIONABLE_ENDPOINT_EVENT_FIELDS } from '../../../../common/endpoint/exceptions/exceptionable_endpoint_event_fields';
|
||||
import { ALERT_ORIGINAL_EVENT } from '../../../../common/field_maps/field_names';
|
||||
|
||||
export const filterIndexPatterns = (
|
||||
|
@ -68,7 +68,7 @@ export const filterIndexPatterns = (
|
|||
return {
|
||||
...patterns,
|
||||
fields: patterns.fields.filter(({ name }) =>
|
||||
exceptionableEndpointEventFields.includes(name)
|
||||
EXCEPTIONABLE_ENDPOINT_EVENT_FIELDS.includes(name)
|
||||
),
|
||||
};
|
||||
default:
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ExceptionListType, ExceptionListTypeEnum } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import {
|
||||
CreateExceptionListSchema,
|
||||
ExceptionListType,
|
||||
ExceptionListTypeEnum,
|
||||
} from '@kbn/securitysolution-io-ts-list-types';
|
||||
import {
|
||||
EXCEPTION_LIST_URL,
|
||||
EXCEPTION_LIST_ITEM_URL,
|
||||
|
@ -15,7 +19,7 @@ import {
|
|||
} from '@kbn/securitysolution-list-constants';
|
||||
|
||||
export const EVENT_FILTER_LIST_TYPE: ExceptionListType = ExceptionListTypeEnum.ENDPOINT_EVENTS;
|
||||
export const EVENT_FILTER_LIST = {
|
||||
export const EVENT_FILTER_LIST: CreateExceptionListSchema = {
|
||||
name: ENDPOINT_EVENT_FILTERS_LIST_NAME,
|
||||
namespace_type: 'agnostic',
|
||||
description: ENDPOINT_EVENT_FILTERS_LIST_DESCRIPTION,
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
ExceptionsListPreCreateItemServerExtension,
|
||||
} from '../../../../../lists/server';
|
||||
import { EndpointAppContextService } from '../../../endpoint/endpoint_app_context_services';
|
||||
import { TrustedAppValidator } from '../validators';
|
||||
import { EventFilterValidator, TrustedAppValidator } from '../validators';
|
||||
|
||||
export const getExceptionsPreCreateItemHandler = (
|
||||
endpointAppContext: EndpointAppContextService
|
||||
|
@ -21,6 +21,11 @@ export const getExceptionsPreCreateItemHandler = (
|
|||
return new TrustedAppValidator(endpointAppContext, request).validatePreCreateItem(data);
|
||||
}
|
||||
|
||||
// Validate event filter
|
||||
if (EventFilterValidator.isEventFilter(data)) {
|
||||
return new EventFilterValidator(endpointAppContext, request).validatePreCreateItem(data);
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
UpdateExceptionListItemOptions,
|
||||
} from '../../../../../lists/server';
|
||||
import { EndpointAppContextService } from '../../../endpoint/endpoint_app_context_services';
|
||||
import { TrustedAppValidator } from '../validators';
|
||||
import { EventFilterValidator, TrustedAppValidator } from '../validators';
|
||||
|
||||
export const getExceptionsPreUpdateItemHandler = (
|
||||
endpointAppContextService: EndpointAppContextService
|
||||
|
@ -30,14 +30,24 @@ export const getExceptionsPreUpdateItemHandler = (
|
|||
return data;
|
||||
}
|
||||
|
||||
const listId = currentSavedItem.list_id;
|
||||
|
||||
// Validate trusted apps
|
||||
if (TrustedAppValidator.isTrustedApp({ listId: currentSavedItem.list_id })) {
|
||||
if (TrustedAppValidator.isTrustedApp({ listId })) {
|
||||
return new TrustedAppValidator(endpointAppContextService, request).validatePreUpdateItem(
|
||||
data,
|
||||
currentSavedItem
|
||||
);
|
||||
}
|
||||
|
||||
// Validate event filter
|
||||
if (EventFilterValidator.isEventFilter({ listId })) {
|
||||
return new EventFilterValidator(endpointAppContextService, request).validatePreUpdateItem(
|
||||
data,
|
||||
currentSavedItem
|
||||
);
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import { ENDPOINT_EVENT_FILTERS_LIST_ID } from '@kbn/securitysolution-list-constants';
|
||||
|
||||
import {
|
||||
CreateExceptionListItemOptions,
|
||||
UpdateExceptionListItemOptions,
|
||||
} from '../../../../../lists/server';
|
||||
import { EXCEPTIONABLE_ENDPOINT_EVENT_FIELDS } from '../../../../common/endpoint/exceptions/exceptionable_endpoint_event_fields';
|
||||
|
||||
import { ExceptionItemLikeOptions } from '../types';
|
||||
|
||||
import { BaseValidator } from './base_validator';
|
||||
import { EndpointArtifactExceptionValidationError } from './errors';
|
||||
|
||||
function validateField(field: string) {
|
||||
if (!EXCEPTIONABLE_ENDPOINT_EVENT_FIELDS.includes(field)) {
|
||||
return `invalid field: ${field}`;
|
||||
}
|
||||
}
|
||||
|
||||
const EntrySchema = schema.object({
|
||||
field: schema.string({ validate: validateField }),
|
||||
operator: schema.oneOf([schema.literal('included'), schema.literal('excluded')]),
|
||||
type: schema.oneOf([schema.literal('match'), schema.literal('match_any')]),
|
||||
value: schema.oneOf([schema.arrayOf(schema.string()), schema.string()]),
|
||||
});
|
||||
|
||||
const NestedEntrySchema = schema.object({
|
||||
field: schema.string({ validate: validateField }),
|
||||
type: schema.literal('nested'),
|
||||
entries: schema.arrayOf(EntrySchema),
|
||||
});
|
||||
|
||||
const EntriesSchema = schema.oneOf([EntrySchema, NestedEntrySchema]);
|
||||
|
||||
const EventFilterDataSchema = schema.object(
|
||||
{
|
||||
entries: schema.arrayOf(EntriesSchema, { minSize: 1 }),
|
||||
},
|
||||
{
|
||||
unknowns: 'ignore',
|
||||
}
|
||||
);
|
||||
|
||||
export class EventFilterValidator extends BaseValidator {
|
||||
static isEventFilter(item: { listId: string }): boolean {
|
||||
return item.listId === ENDPOINT_EVENT_FILTERS_LIST_ID;
|
||||
}
|
||||
|
||||
async validatePreCreateItem(item: CreateExceptionListItemOptions) {
|
||||
await this.validateCanManageEndpointArtifacts();
|
||||
await this.validateEventFilterData(item);
|
||||
|
||||
// user can always create a global entry so additional checks not needed
|
||||
if (this.isItemByPolicy(item)) {
|
||||
await this.validateCanCreateByPolicyArtifacts(item);
|
||||
await this.validateByPolicyItem(item);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
async validatePreUpdateItem(
|
||||
_updatedItem: UpdateExceptionListItemOptions,
|
||||
currentItem: ExceptionListItemSchema
|
||||
): Promise<UpdateExceptionListItemOptions> {
|
||||
const updatedItem = _updatedItem as ExceptionItemLikeOptions;
|
||||
|
||||
await this.validateCanManageEndpointArtifacts();
|
||||
await this.validateEventFilterData(updatedItem);
|
||||
|
||||
try {
|
||||
await this.validateCanCreateByPolicyArtifacts(updatedItem);
|
||||
} catch (noByPolicyAuthzError) {
|
||||
// Not allowed to create/update by policy data. Validate that the effective scope of the item
|
||||
// remained unchanged with this update or was set to `global` (only allowed update). If not,
|
||||
// then throw the validation error that was catch'ed
|
||||
if (this.wasByPolicyEffectScopeChanged(updatedItem, currentItem)) {
|
||||
throw noByPolicyAuthzError;
|
||||
}
|
||||
}
|
||||
|
||||
await this.validateByPolicyItem(updatedItem);
|
||||
return _updatedItem;
|
||||
}
|
||||
|
||||
private async validateEventFilterData(item: ExceptionItemLikeOptions): Promise<void> {
|
||||
await this.validateBasicData(item);
|
||||
|
||||
try {
|
||||
EventFilterDataSchema.validate(item);
|
||||
} catch (error) {
|
||||
throw new EndpointArtifactExceptionValidationError(error.message);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,3 +6,4 @@
|
|||
*/
|
||||
|
||||
export { TrustedAppValidator } from './trusted_app_validator';
|
||||
export { EventFilterValidator } from './event_filter_validator';
|
||||
|
|
|
@ -16,6 +16,7 @@ import { FtrService } from '../../functional/ftr_provider_context';
|
|||
import { ExceptionsListItemGenerator } from '../../../plugins/security_solution/common/endpoint/data_generators/exceptions_list_item_generator';
|
||||
import { TRUSTED_APPS_EXCEPTION_LIST_DEFINITION } from '../../../plugins/security_solution/public/management/pages/trusted_apps/constants';
|
||||
import { EndpointError } from '../../../plugins/security_solution/common/endpoint/errors';
|
||||
import { EVENT_FILTER_LIST } from '../../../plugins/security_solution/public/management/pages/event_filters/constants';
|
||||
|
||||
export interface ArtifactTestData {
|
||||
artifact: ExceptionListItemSchema;
|
||||
|
@ -86,4 +87,13 @@ export class EndpointArtifactsTestResources extends FtrService {
|
|||
|
||||
return this.createExceptionItem(trustedApp);
|
||||
}
|
||||
|
||||
async createEventFilter(
|
||||
overrides: Partial<CreateExceptionListItemSchema> = {}
|
||||
): Promise<ArtifactTestData> {
|
||||
await this.ensureListExists(EVENT_FILTER_LIST);
|
||||
const eventFilter = this.exceptionsGenerator.generateEventFilterForCreate(overrides);
|
||||
|
||||
return this.createExceptionItem(eventFilter);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { EXCEPTION_LIST_ITEM_URL } from '@kbn/securitysolution-list-constants';
|
||||
import { ExceptionListItemSchema } from '@kbn/securitysolution-io-ts-list-types';
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
import { PolicyTestResourceInfo } from '../../../security_solution_endpoint/services/endpoint_policy';
|
||||
import { ArtifactTestData } from '../../../security_solution_endpoint/services/endpoint_artifacts';
|
||||
import { BY_POLICY_ARTIFACT_TAG_PREFIX } from '../../../../plugins/security_solution/common/endpoint/service/artifacts';
|
||||
import { ExceptionsListItemGenerator } from '../../../../plugins/security_solution/common/endpoint/data_generators/exceptions_list_item_generator';
|
||||
import {
|
||||
createUserAndRole,
|
||||
deleteUserAndRole,
|
||||
ROLES,
|
||||
} from '../../../common/services/security_solution';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
const endpointPolicyTestResources = getService('endpointPolicyTestResources');
|
||||
const endpointArtifactTestResources = getService('endpointArtifactTestResources');
|
||||
|
||||
describe('Endpoint artifacts (via lists plugin) event filter', () => {
|
||||
let fleetEndpointPolicy: PolicyTestResourceInfo;
|
||||
|
||||
before(async () => {
|
||||
// Create an endpoint policy in fleet we can work with
|
||||
fleetEndpointPolicy = await endpointPolicyTestResources.createPolicy();
|
||||
|
||||
// create role/user
|
||||
await createUserAndRole(getService, ROLES.detections_admin);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
if (fleetEndpointPolicy) {
|
||||
await fleetEndpointPolicy.cleanup();
|
||||
}
|
||||
|
||||
// delete role/user
|
||||
await deleteUserAndRole(getService, ROLES.detections_admin);
|
||||
});
|
||||
|
||||
const anEndpointArtifactError = (res: { body: { message: string } }) => {
|
||||
expect(res.body.message).to.match(/EndpointArtifactError/);
|
||||
};
|
||||
const anErrorMessageWith = (
|
||||
value: string | RegExp
|
||||
): ((res: { body: { message: string } }) => void) => {
|
||||
return (res) => {
|
||||
if (value instanceof RegExp) {
|
||||
expect(res.body.message).to.match(value);
|
||||
} else {
|
||||
expect(res.body.message).to.be(value);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const exceptionsGenerator = new ExceptionsListItemGenerator();
|
||||
let eventFilterData: ArtifactTestData;
|
||||
|
||||
type EventFilterApiCallsInterface = Array<{
|
||||
method: keyof Pick<typeof supertest, 'post' | 'put'>;
|
||||
path: string;
|
||||
// The body just needs to have the properties we care about in the tests. This should cover most
|
||||
// mocks used for testing that support different interfaces
|
||||
getBody: (
|
||||
overrides: Partial<ExceptionListItemSchema>
|
||||
) => Pick<ExceptionListItemSchema, 'os_types' | 'tags' | 'entries'>;
|
||||
}>;
|
||||
|
||||
const eventFilterCalls: EventFilterApiCallsInterface = [
|
||||
{
|
||||
method: 'post',
|
||||
path: EXCEPTION_LIST_ITEM_URL,
|
||||
getBody: (overrides) =>
|
||||
exceptionsGenerator.generateEventFilterForCreate({
|
||||
tags: eventFilterData.artifact.tags,
|
||||
...overrides,
|
||||
}),
|
||||
},
|
||||
{
|
||||
method: 'put',
|
||||
path: EXCEPTION_LIST_ITEM_URL,
|
||||
getBody: (overrides) =>
|
||||
exceptionsGenerator.generateEventFilterForUpdate({
|
||||
id: eventFilterData.artifact.id,
|
||||
item_id: eventFilterData.artifact.item_id,
|
||||
tags: eventFilterData.artifact.tags,
|
||||
_version: eventFilterData.artifact._version,
|
||||
...overrides,
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
beforeEach(async () => {
|
||||
eventFilterData = await endpointArtifactTestResources.createEventFilter({
|
||||
tags: [`${BY_POLICY_ARTIFACT_TAG_PREFIX}${fleetEndpointPolicy.packagePolicy.id}`],
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
if (eventFilterData) {
|
||||
await eventFilterData.cleanup();
|
||||
}
|
||||
});
|
||||
|
||||
describe('and has authorization to manage endpoint security', () => {
|
||||
for (const eventFilterCall of eventFilterCalls) {
|
||||
it(`should error on [${eventFilterCall.method} if invalid field`, async () => {
|
||||
const body = eventFilterCall.getBody({});
|
||||
|
||||
body.entries[0].field = 'some.invalid.field';
|
||||
|
||||
await supertest[eventFilterCall.method](eventFilterCall.path)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(body)
|
||||
.expect(400)
|
||||
.expect(anEndpointArtifactError)
|
||||
.expect(anErrorMessageWith(/types that failed validation:/));
|
||||
});
|
||||
|
||||
it(`should error on [${eventFilterCall.method}] if more than one OS is set`, async () => {
|
||||
const body = eventFilterCall.getBody({ os_types: ['linux', 'windows'] });
|
||||
|
||||
await supertest[eventFilterCall.method](eventFilterCall.path)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(body)
|
||||
.expect(400)
|
||||
.expect(anEndpointArtifactError)
|
||||
.expect(anErrorMessageWith(/\[osTypes\]: array size is \[2\]/));
|
||||
});
|
||||
|
||||
it(`should error on [${eventFilterCall.method}] if policy id is invalid`, async () => {
|
||||
const body = eventFilterCall.getBody({
|
||||
tags: [`${BY_POLICY_ARTIFACT_TAG_PREFIX}123`],
|
||||
});
|
||||
|
||||
await supertest[eventFilterCall.method](eventFilterCall.path)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(body)
|
||||
.expect(400)
|
||||
.expect(anEndpointArtifactError)
|
||||
.expect(anErrorMessageWith(/invalid policy ids/));
|
||||
});
|
||||
|
||||
it(`should work on [${eventFilterCall.method}] with valid entry`, async () => {
|
||||
const body = eventFilterCall.getBody({});
|
||||
|
||||
await supertest[eventFilterCall.method](eventFilterCall.path)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(body)
|
||||
.expect(200);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
describe('and user DOES NOT have authorization to manage endpoint security', () => {
|
||||
for (const eventFilterCall of eventFilterCalls) {
|
||||
it(`should 403 on [${eventFilterCall.method}]`, async () => {
|
||||
await supertestWithoutAuth[eventFilterCall.method](eventFilterCall.path)
|
||||
.auth(ROLES.detections_admin, 'changeme')
|
||||
.set('kbn-xsrf', 'true')
|
||||
.send(eventFilterCall.getBody({}))
|
||||
.expect(403, {
|
||||
status_code: 403,
|
||||
message: 'EndpointArtifactError: Endpoint authorization failure',
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
|
@ -33,5 +33,6 @@ export default function endpointAPIIntegrationTests(providerContext: FtrProvider
|
|||
loadTestFile(require.resolve('./package'));
|
||||
loadTestFile(require.resolve('./endpoint_authz'));
|
||||
loadTestFile(require.resolve('./endpoint_artifacts'));
|
||||
loadTestFile(require.resolve('./endpoint_artifacts/event_filter'));
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue