Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
5b4a824
[Entity Analytics] Migrate explore pages (hosts/users) to use EUID
YulNaumenko Mar 2, 2026
2a48d8c
Merge branch 'main' into migrate-explore-euid-pr2-explore
YulNaumenko Mar 19, 2026
a4475c4
Merge branch 'main' into migrate-explore-euid-pr2-explore
YulNaumenko Mar 26, 2026
a0e2318
Merge remote-tracking branch 'upstream/main' into migrate-explore-eui…
YulNaumenko Mar 27, 2026
501e428
-
YulNaumenko Mar 28, 2026
7a09793
-
YulNaumenko Mar 28, 2026
4ee4444
-
YulNaumenko Mar 28, 2026
9b15371
-
YulNaumenko Mar 29, 2026
6c8b395
Merge branch 'main' into migrate-explore-euid-pr2-explore
YulNaumenko Mar 29, 2026
fd7aa1f
Changes from node scripts/eslint_all_files --no-cache --fix
kibanamachine Mar 29, 2026
89e7593
-
YulNaumenko Mar 30, 2026
e50f359
Merge branch 'migrate-explore-euid-pr2-explore' of github.com:YulNaum…
YulNaumenko Mar 30, 2026
7045ddf
-
YulNaumenko Mar 30, 2026
ba0a37f
-
YulNaumenko Mar 30, 2026
24235f5
Merge branch 'main' into migrate-explore-euid-pr2-explore
YulNaumenko Mar 30, 2026
9658fc5
-
YulNaumenko Mar 30, 2026
190f13d
Merge branch 'migrate-explore-euid-pr2-explore' of github.com:YulNaum…
YulNaumenko Mar 30, 2026
2388912
fixed tests
YulNaumenko Mar 30, 2026
41986f8
-
YulNaumenko Mar 30, 2026
002cc17
-
YulNaumenko Mar 30, 2026
a019eb6
Merge branch 'main' into migrate-explore-euid-pr2-explore
YulNaumenko Mar 30, 2026
cfa61a0
Merge branch 'main' into migrate-explore-euid-pr2-explore
YulNaumenko Mar 30, 2026
3436833
-
YulNaumenko Mar 31, 2026
48e86cc
-
YulNaumenko Mar 31, 2026
aac51cb
-
YulNaumenko Apr 1, 2026
e33f3d3
Merge branch 'main' into migrate-explore-euid-pr2-explore
YulNaumenko Apr 1, 2026
ed19830
-
YulNaumenko Apr 2, 2026
cb035e9
-
YulNaumenko Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35820,7 +35820,6 @@
"xpack.securitySolution.entityAnalytics.entityStore.entitiesList.tableTitle": "Entitäten",
"xpack.securitySolution.entityAnalytics.entityStore.entitiesList.tableTooltip": "Es kann einige Minuten dauern, bis Entitätsdaten angezeigt werden",
"xpack.securitySolution.entityAnalytics.entityStore.entitySource.filterTitle": "Quelle",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.criticalityDescription": "Kritikalität von Assets",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.eventDescription": "Ereignisse",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.riskDescription": "Risiko",
"xpack.securitySolution.entityAnalytics.header.anomalies": "Anomalien",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36198,7 +36198,6 @@
"xpack.securitySolution.entityAnalytics.entityStore.entitiesList.tableTitle": "Entités",
"xpack.securitySolution.entityAnalytics.entityStore.entitiesList.tableTooltip": "L’affichage des données d'entité peut prendre quelques minutes",
"xpack.securitySolution.entityAnalytics.entityStore.entitySource.filterTitle": "Source",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.criticalityDescription": "Criticité des ressources",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.eventDescription": "Événements",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.riskDescription": "Risque",
"xpack.securitySolution.entityAnalytics.header.anomalies": "Anomalies",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36253,7 +36253,6 @@
"xpack.securitySolution.entityAnalytics.entityStore.entitiesList.tableTitle": "エンティティ",
"xpack.securitySolution.entityAnalytics.entityStore.entitiesList.tableTooltip": "エンティティデータが表示されるまでに数分かかる場合があります",
"xpack.securitySolution.entityAnalytics.entityStore.entitySource.filterTitle": "送信元",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.criticalityDescription": "アセット重要度",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.eventDescription": "イベント",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.riskDescription": "リスク",
"xpack.securitySolution.entityAnalytics.header.anomalies": "異常",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36233,7 +36233,6 @@
"xpack.securitySolution.entityAnalytics.entityStore.entitiesList.tableTitle": "实体",
"xpack.securitySolution.entityAnalytics.entityStore.entitiesList.tableTooltip": "实体数据可能需要几分钟才能显示",
"xpack.securitySolution.entityAnalytics.entityStore.entitySource.filterTitle": "源",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.criticalityDescription": "资产关键度",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.eventDescription": "事件",
"xpack.securitySolution.entityAnalytics.entityStore.helpers.sourceField.riskDescription": "风险",
"xpack.securitySolution.entityAnalytics.header.anomalies": "异常",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* 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 { z } from '@kbn/zod/v4';
import type { HostEntity } from '../../api/entity_analytics/entity_store/entities/common.gen';
import { UpsertEntitiesBulkRequestBody } from '../../api/entity_analytics/entity_store/entities/upsert_entities_bulk.gen';
import {
preprocessUpsertEntitiesBulkRequestBody,
sanitizeEntityRecordForUpsert,
} from './sanitize_entity_record_for_upsert';

const bulkBodySchema = z.preprocess(
preprocessUpsertEntitiesBulkRequestBody,
UpsertEntitiesBulkRequestBody
);

describe('sanitize_entity_record_for_upsert', () => {
it('coerces host.risk.inputs object to array and notes string to array', () => {
const record = {
entity: {
id: 'host:test',
type: 'host',
attributes: { watchlists: ['wl-1'], asset: true },
behaviors: { rule_names: ['a'], brute_force_victim: true },
relationships: {
communicates_with: ['host:a'],
resolution: { risk: { calculated_level: 'Low' } },
},
},
host: {
name: 'h1',
risk: {
'@timestamp': '2026-03-28T01:41:12.286Z',
id_field: 'host.name',
id_value: 'h1',
calculated_level: 'Moderate',
calculated_score: 42.5,
calculated_score_norm: 55,
category_1_score: 30,
category_1_count: 3,
inputs: {
id: 'alert-1',
index: '.alerts',
category: 'category_1',
description: 'demo',
risk_score: 65,
timestamp: '2026-03-28T01:41:12.286Z',
contribution_score: 12,
},
notes: 'one note',
criticality_level: 'medium_impact',
},
},
event: { ingested: '2026-03-28T01:41:12.286Z' },
};

const out = sanitizeEntityRecordForUpsert(record as never);

expect(
(out as { host?: { risk?: { inputs?: unknown; notes?: unknown } } }).host?.risk?.inputs
).toEqual([
{
id: 'alert-1',
index: '.alerts',
category: 'category_1',
description: 'demo',
risk_score: 65,
timestamp: '2026-03-28T01:41:12.286Z',
contribution_score: 12,
},
]);
expect((out as { host?: { risk?: { notes?: string[] } } }).host?.risk?.notes).toEqual([
'one note',
]);
expect(
(out as { entity?: { attributes?: { watchlists?: unknown } } }).entity?.attributes
).toEqual({
asset: true,
});
expect(
(out as { entity?: { behaviors?: { rule_names?: unknown; brute_force_victim?: boolean } } })
.entity?.behaviors
).toEqual({ brute_force_victim: true });
expect(
(
out as {
entity?: { relationships?: { communicates_with?: string[]; resolution?: unknown } };
}
).entity?.relationships
).toEqual({ communicates_with: ['host:a'] });
});

it('accepts bulk body with doc instead of record after preprocess + Zod', () => {
const raw = {
entities: [
{
type: 'host',
doc: {
entity: { id: 'host:x', type: 'host' },
host: { name: 'host-a' },
},
},
],
};

const parsed = bulkBodySchema.safeParse(raw);
expect(parsed.success).toBe(true);
if (parsed.success) {
const record = parsed.data.entities[0].record as HostEntity;
expect(record.host?.name).toBe('host-a');
}
});
});
Loading
Loading