Skip to content

Commit ee57c56

Browse files
authored
Add entity definitions for user, service, and generic entity types (#249637)
closes #246849
1 parent ea8cf4d commit ee57c56

File tree

5 files changed

+239
-7
lines changed

5 files changed

+239
-7
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { newestValue } from './field_retention_operations';
9+
import type { EntityDefinitionWithoutId } from './entity_schema';
10+
import { getCommonFieldDescriptions, getEntityFieldsDescriptions } from './common_fields';
11+
12+
export const GENERIC_IDENTITY_FIELD = 'entity.id';
13+
14+
export const genericEntityDefinition: EntityDefinitionWithoutId = {
15+
type: 'generic',
16+
name: `Security 'generic' Entity Store Definition`,
17+
identityFields: [{ field: GENERIC_IDENTITY_FIELD, mapping: { type: 'keyword' } }],
18+
indexPatterns: [],
19+
fields: [
20+
...getEntityFieldsDescriptions(),
21+
22+
newestValue({ source: 'cloud.account.id' }),
23+
newestValue({ source: 'cloud.account.name' }),
24+
newestValue({ source: 'cloud.availability_zone' }),
25+
newestValue({ source: 'cloud.instance.id' }),
26+
newestValue({ source: 'cloud.instance.name' }),
27+
newestValue({ source: 'cloud.machine.type' }),
28+
newestValue({ source: 'cloud.project.id' }),
29+
newestValue({ source: 'cloud.project.name' }),
30+
newestValue({ source: 'cloud.provider' }),
31+
newestValue({ source: 'cloud.region' }),
32+
newestValue({ source: 'cloud.service.name' }),
33+
34+
newestValue({ source: 'host.architecture' }),
35+
newestValue({ source: 'host.boot.id' }),
36+
newestValue({ source: 'host.cpu.usage' }),
37+
newestValue({ source: 'host.disk.read.bytes' }),
38+
newestValue({ source: 'host.disk.write.bytes' }),
39+
newestValue({ source: 'host.domain' }),
40+
newestValue({ source: 'host.hostname' }),
41+
newestValue({ source: 'host.id' }),
42+
newestValue({ source: 'host.mac' }),
43+
newestValue({ source: 'host.name' }),
44+
newestValue({ source: 'host.network.egress.bytes' }),
45+
newestValue({ source: 'host.network.egress.packets' }),
46+
newestValue({ source: 'host.network.ingress.bytes' }),
47+
newestValue({ source: 'host.network.ingress.packets' }),
48+
newestValue({ source: 'host.pid_ns_ino' }),
49+
newestValue({ source: 'host.type' }),
50+
newestValue({ source: 'host.uptime' }),
51+
newestValue({
52+
source: 'host.ip',
53+
mapping: {
54+
type: 'ip',
55+
},
56+
}),
57+
58+
newestValue({ source: 'user.domain' }),
59+
newestValue({ source: 'user.email' }),
60+
newestValue({ source: 'user.roles' }),
61+
newestValue({ source: 'user.hash' }),
62+
newestValue({ source: 'user.id' }),
63+
newestValue({
64+
source: 'user.name',
65+
mapping: {
66+
type: 'keyword',
67+
fields: {
68+
text: {
69+
type: 'match_only_text',
70+
},
71+
},
72+
},
73+
}),
74+
newestValue({
75+
source: 'user.full_name',
76+
mapping: {
77+
type: 'keyword',
78+
fields: {
79+
text: {
80+
type: 'match_only_text',
81+
},
82+
},
83+
},
84+
}),
85+
86+
newestValue({ source: 'orchestrator.api_version' }),
87+
newestValue({ source: 'orchestrator.cluster.id' }),
88+
newestValue({ source: 'orchestrator.cluster.name' }),
89+
newestValue({ source: 'orchestrator.cluster.url' }),
90+
newestValue({ source: 'orchestrator.cluster.version' }),
91+
newestValue({ source: 'orchestrator.namespace' }),
92+
newestValue({ source: 'orchestrator.organization' }),
93+
newestValue({ source: 'orchestrator.resource.annotation' }),
94+
newestValue({ source: 'orchestrator.resource.id' }),
95+
newestValue({ source: 'orchestrator.resource.ip' }),
96+
newestValue({ source: 'orchestrator.resource.label' }),
97+
newestValue({ source: 'orchestrator.resource.name' }),
98+
newestValue({ source: 'orchestrator.resource.parent.type' }),
99+
newestValue({ source: 'orchestrator.resource.type' }),
100+
newestValue({ source: 'orchestrator.type' }),
101+
102+
...getCommonFieldDescriptions('entity'),
103+
],
104+
};

x-pack/solutions/security/plugins/entity_store/server/domain/definitions/host.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ export const HOST_IDENTITY_FIELD = 'host.name';
1313

1414
// Mostly copied from x-pack/solutions/security/plugins/security_solution/server/lib/entity_analytics/entity_store/entity_definitions/entity_descriptions/host.ts
1515

16-
export const hostEntityDescription: EntityDefinitionWithoutId = {
16+
export const hostEntityDefinition: EntityDefinitionWithoutId = {
1717
type: 'host',
1818
name: `Security 'host' Entity Store Definition`,
1919
identityFields: [{ field: HOST_IDENTITY_FIELD, mapping: { type: 'keyword' } }],

x-pack/solutions/security/plugins/entity_store/server/domain/definitions/registry.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,20 @@
66
*/
77

88
import assert from 'node:assert';
9-
import { hostEntityDescription } from './host';
9+
1010
import type { EntityType } from './entity_schema';
1111
import { type EntityDefinitionWithoutId, type ManagedEntityDefinition } from './entity_schema';
1212
import { getEntityDefinitionId } from '../assets/latest_index';
13+
import { hostEntityDefinition } from './host';
14+
import { userEntityDefinition } from './user';
15+
import { serviceEntityDefinition } from './service';
16+
import { genericEntityDefinition } from './generic';
1317

1418
const entitiesDescriptionRegistry = {
15-
host: hostEntityDescription,
16-
// TODO: add other entity descriptions
17-
user: hostEntityDescription,
18-
service: hostEntityDescription,
19-
generic: hostEntityDescription,
19+
host: hostEntityDefinition,
20+
user: userEntityDefinition,
21+
service: serviceEntityDefinition,
22+
generic: genericEntityDefinition,
2023
} as const satisfies Record<EntityType, EntityDefinitionWithoutId>;
2124

2225
interface EntityDefinitionParams {
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { getCommonFieldDescriptions, getEntityFieldsDescriptions } from './common_fields';
9+
import type { EntityDefinitionWithoutId } from './entity_schema';
10+
import { collectValues as collect, newestValue } from './field_retention_operations';
11+
12+
export const SERVICE_IDENTITY_FIELD = 'service.name';
13+
14+
export const serviceEntityDefinition: EntityDefinitionWithoutId = {
15+
type: 'service',
16+
name: `Security 'service' Entity Store Definition`,
17+
identityFields: [{ field: SERVICE_IDENTITY_FIELD, mapping: { type: 'keyword' } }],
18+
indexPatterns: [],
19+
fields: [
20+
collect({ source: 'service.address' }),
21+
collect({ source: 'service.environment' }),
22+
collect({ source: 'service.ephemeral_id' }),
23+
collect({ source: 'service.id' }),
24+
collect({ source: 'service.node.name' }),
25+
collect({ source: 'service.node.roles' }),
26+
collect({ source: 'service.node.role' }),
27+
newestValue({ source: 'service.state' }),
28+
collect({ source: 'service.type' }),
29+
newestValue({ source: 'service.version' }),
30+
...getCommonFieldDescriptions('service'),
31+
...getEntityFieldsDescriptions('service'),
32+
33+
collect({
34+
source: `service.entity.relationships.Communicates_with`,
35+
destination: 'entity.relationships.Communicates_with',
36+
mapping: { type: 'keyword' },
37+
allowAPIUpdate: true,
38+
}),
39+
collect({
40+
source: `service.entity.relationships.Depends_on`,
41+
destination: 'entity.relationships.Depends_on',
42+
mapping: { type: 'keyword' },
43+
allowAPIUpdate: true,
44+
}),
45+
collect({
46+
source: `service.entity.relationships.Dependent_of`,
47+
destination: 'entity.relationships.Dependent_of',
48+
mapping: { type: 'keyword' },
49+
allowAPIUpdate: true,
50+
}),
51+
],
52+
};
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import { getCommonFieldDescriptions, getEntityFieldsDescriptions } from './common_fields';
9+
import type { EntityDefinitionWithoutId } from './entity_schema';
10+
import { collectValues as collect } from './field_retention_operations';
11+
12+
export const USER_IDENTITY_FIELD = 'user.name';
13+
14+
export const userEntityDefinition: EntityDefinitionWithoutId = {
15+
type: 'user',
16+
name: `Security 'user' Entity Store Definition`,
17+
identityFields: [
18+
{
19+
field: USER_IDENTITY_FIELD,
20+
mapping: {
21+
type: 'keyword',
22+
fields: { text: { type: 'match_only_text' } },
23+
},
24+
},
25+
],
26+
indexPatterns: [],
27+
fields: [
28+
collect({ source: 'user.domain' }),
29+
collect({ source: 'user.email' }),
30+
collect({
31+
source: 'user.full_name',
32+
mapping: {
33+
type: 'keyword',
34+
fields: {
35+
text: {
36+
type: 'match_only_text',
37+
},
38+
},
39+
},
40+
}),
41+
collect({ source: 'user.hash' }),
42+
collect({ source: 'user.id' }),
43+
collect({ source: 'user.roles' }),
44+
...getCommonFieldDescriptions('user'),
45+
...getEntityFieldsDescriptions('user'),
46+
47+
collect({
48+
source: `user.entity.relationships.Accesses_frequently`,
49+
destination: 'entity.relationships.Accesses_frequently',
50+
mapping: { type: 'keyword' },
51+
allowAPIUpdate: true,
52+
}),
53+
collect({
54+
source: `user.entity.relationships.Owns`,
55+
destination: 'entity.relationships.Owns',
56+
mapping: { type: 'keyword' },
57+
allowAPIUpdate: true,
58+
}),
59+
60+
collect({
61+
source: `user.entity.relationships.Supervises`,
62+
destination: 'entity.relationships.Supervises',
63+
mapping: { type: 'keyword' },
64+
allowAPIUpdate: true,
65+
}),
66+
collect({
67+
source: `user.entity.relationships.Supervised_by`,
68+
destination: 'entity.relationships.Supervised_by',
69+
mapping: { type: 'keyword' },
70+
allowAPIUpdate: true,
71+
}),
72+
],
73+
};

0 commit comments

Comments
 (0)