[Security] Add telemetry for new protection types and arrays of objects (#97624)
* Add telemetry for new protection types and arrays of objects * Add malware_signature to process.Ext + dll.Ext * Fix comments for base fields * Move naming convention disable to a line * Fix unit test for rule.version
This commit is contained in:
parent
43850fae72
commit
8b20cbc3d8
2 changed files with 113 additions and 48 deletions
|
@ -38,6 +38,7 @@ describe('TelemetryEventsSender', () => {
|
||||||
id: 'X',
|
id: 'X',
|
||||||
name: 'Y',
|
name: 'Y',
|
||||||
ruleset: 'Z',
|
ruleset: 'Z',
|
||||||
|
version: '100',
|
||||||
},
|
},
|
||||||
file: {
|
file: {
|
||||||
size: 3,
|
size: 3,
|
||||||
|
@ -97,6 +98,7 @@ describe('TelemetryEventsSender', () => {
|
||||||
id: 'X',
|
id: 'X',
|
||||||
name: 'Y',
|
name: 'Y',
|
||||||
ruleset: 'Z',
|
ruleset: 'Z',
|
||||||
|
version: '100',
|
||||||
},
|
},
|
||||||
file: {
|
file: {
|
||||||
size: 3,
|
size: 3,
|
||||||
|
@ -253,6 +255,57 @@ describe('allowlistEventFields', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('filters arrays of objects', () => {
|
||||||
|
const event = {
|
||||||
|
a: [
|
||||||
|
{
|
||||||
|
a1: 'a1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
b: {
|
||||||
|
b1: 'b1',
|
||||||
|
},
|
||||||
|
c: [
|
||||||
|
{
|
||||||
|
d: 'd1',
|
||||||
|
e: 'e1',
|
||||||
|
f: 'f1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
d: 'd2',
|
||||||
|
e: 'e2',
|
||||||
|
f: 'f2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
d: 'd3',
|
||||||
|
e: 'e3',
|
||||||
|
f: 'f3',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
expect(copyAllowlistedFields(allowlist, event)).toStrictEqual({
|
||||||
|
a: [
|
||||||
|
{
|
||||||
|
a1: 'a1',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
b: {
|
||||||
|
b1: 'b1',
|
||||||
|
},
|
||||||
|
c: [
|
||||||
|
{
|
||||||
|
d: 'd1',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
d: 'd2',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
d: 'd3',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it("doesn't create empty objects", () => {
|
it("doesn't create empty objects", () => {
|
||||||
const event = {
|
const event = {
|
||||||
a: 'a',
|
a: 'a',
|
||||||
|
|
|
@ -21,16 +21,8 @@ import {
|
||||||
} from '../../../../task_manager/server';
|
} from '../../../../task_manager/server';
|
||||||
import { TelemetryDiagTask } from './task';
|
import { TelemetryDiagTask } from './task';
|
||||||
|
|
||||||
export type SearchTypes =
|
type BaseSearchTypes = string | number | boolean | object;
|
||||||
| string
|
export type SearchTypes = BaseSearchTypes | BaseSearchTypes[] | undefined;
|
||||||
| string[]
|
|
||||||
| number
|
|
||||||
| number[]
|
|
||||||
| boolean
|
|
||||||
| boolean[]
|
|
||||||
| object
|
|
||||||
| object[]
|
|
||||||
| undefined;
|
|
||||||
|
|
||||||
export interface TelemetryEvent {
|
export interface TelemetryEvent {
|
||||||
[key: string]: SearchTypes;
|
[key: string]: SearchTypes;
|
||||||
|
@ -294,8 +286,8 @@ interface AllowlistFields {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allow list process fields within events. This includes "process" and "Target.process".'
|
// Allow list process fields within events. This includes "process" and "Target.process".'
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
|
||||||
const allowlistProcessFields: AllowlistFields = {
|
const allowlistProcessFields: AllowlistFields = {
|
||||||
|
args: true,
|
||||||
name: true,
|
name: true,
|
||||||
executable: true,
|
executable: true,
|
||||||
command_line: true,
|
command_line: true,
|
||||||
|
@ -306,48 +298,23 @@ const allowlistProcessFields: AllowlistFields = {
|
||||||
architecture: true,
|
architecture: true,
|
||||||
code_signature: true,
|
code_signature: true,
|
||||||
dll: true,
|
dll: true,
|
||||||
|
malware_signature: true,
|
||||||
token: {
|
token: {
|
||||||
integrity_level_name: true,
|
integrity_level_name: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
parent: {
|
|
||||||
name: true,
|
|
||||||
executable: true,
|
|
||||||
command_line: true,
|
|
||||||
hash: true,
|
|
||||||
Ext: {
|
|
||||||
architecture: true,
|
|
||||||
code_signature: true,
|
|
||||||
dll: true,
|
|
||||||
token: {
|
|
||||||
integrity_level_name: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
uptime: true,
|
|
||||||
pid: true,
|
|
||||||
ppid: true,
|
|
||||||
},
|
|
||||||
thread: true,
|
thread: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allow list for the data we include in the events. True means that it is deep-cloned
|
// Allow list for event-related fields, which can also be nested under events[]
|
||||||
// blindly. Object contents means that we only copy the fields that appear explicitly in
|
const allowlistBaseEventFields: AllowlistFields = {
|
||||||
// the sub-object.
|
dll: {
|
||||||
const allowlistEventFields: AllowlistFields = {
|
|
||||||
'@timestamp': true,
|
|
||||||
agent: true,
|
|
||||||
Endpoint: true,
|
|
||||||
Memory_protection: true,
|
|
||||||
Ransomware: true,
|
|
||||||
data_stream: true,
|
|
||||||
ecs: true,
|
|
||||||
elastic: true,
|
|
||||||
event: true,
|
|
||||||
rule: {
|
|
||||||
id: true,
|
|
||||||
name: true,
|
name: true,
|
||||||
ruleset: true,
|
path: true,
|
||||||
|
code_signature: true,
|
||||||
|
malware_signature: true,
|
||||||
},
|
},
|
||||||
|
event: true,
|
||||||
file: {
|
file: {
|
||||||
name: true,
|
name: true,
|
||||||
path: true,
|
path: true,
|
||||||
|
@ -365,13 +332,52 @@ const allowlistEventFields: AllowlistFields = {
|
||||||
quarantine_message: true,
|
quarantine_message: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
process: {
|
||||||
|
parent: allowlistProcessFields,
|
||||||
|
...allowlistProcessFields,
|
||||||
|
},
|
||||||
|
network: {
|
||||||
|
direction: true,
|
||||||
|
},
|
||||||
|
registry: {
|
||||||
|
hive: true,
|
||||||
|
key: true,
|
||||||
|
path: true,
|
||||||
|
value: true,
|
||||||
|
},
|
||||||
|
Target: {
|
||||||
|
process: {
|
||||||
|
parent: allowlistProcessFields,
|
||||||
|
...allowlistProcessFields,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Allow list for the data we include in the events. True means that it is deep-cloned
|
||||||
|
// blindly. Object contents means that we only copy the fields that appear explicitly in
|
||||||
|
// the sub-object.
|
||||||
|
const allowlistEventFields: AllowlistFields = {
|
||||||
|
'@timestamp': true,
|
||||||
|
agent: true,
|
||||||
|
Endpoint: true,
|
||||||
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
|
Memory_protection: true,
|
||||||
|
Ransomware: true,
|
||||||
|
data_stream: true,
|
||||||
|
ecs: true,
|
||||||
|
elastic: true,
|
||||||
|
// behavioral protection re-nests some field sets under events.*
|
||||||
|
events: allowlistBaseEventFields,
|
||||||
|
rule: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
ruleset: true,
|
||||||
|
version: true,
|
||||||
|
},
|
||||||
host: {
|
host: {
|
||||||
os: true,
|
os: true,
|
||||||
},
|
},
|
||||||
process: allowlistProcessFields,
|
...allowlistBaseEventFields,
|
||||||
Target: {
|
|
||||||
process: allowlistProcessFields,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export function copyAllowlistedFields(
|
export function copyAllowlistedFields(
|
||||||
|
@ -383,6 +389,12 @@ export function copyAllowlistedFields(
|
||||||
if (eventValue !== null && eventValue !== undefined) {
|
if (eventValue !== null && eventValue !== undefined) {
|
||||||
if (allowValue === true) {
|
if (allowValue === true) {
|
||||||
return { ...newEvent, [allowKey]: eventValue };
|
return { ...newEvent, [allowKey]: eventValue };
|
||||||
|
} else if (typeof allowValue === 'object' && Array.isArray(eventValue)) {
|
||||||
|
const subValues = eventValue.filter((v) => typeof v === 'object');
|
||||||
|
return {
|
||||||
|
...newEvent,
|
||||||
|
[allowKey]: subValues.map((v) => copyAllowlistedFields(allowValue, v as TelemetryEvent)),
|
||||||
|
};
|
||||||
} else if (typeof allowValue === 'object' && typeof eventValue === 'object') {
|
} else if (typeof allowValue === 'object' && typeof eventValue === 'object') {
|
||||||
const values = copyAllowlistedFields(allowValue, eventValue as TelemetryEvent);
|
const values = copyAllowlistedFields(allowValue, eventValue as TelemetryEvent);
|
||||||
return {
|
return {
|
||||||
|
|
Loading…
Reference in a new issue