From c295c67b802c7482466c9c02e4929b79f75638f0 Mon Sep 17 00:00:00 2001 From: Yara Tercero Date: Mon, 23 Oct 2023 17:21:10 -0700 Subject: [PATCH] [Security Solution][DE] Investigation fields telemetry (#169482) ## Summary Adds telemetry to determine the number of users utilizing `investigation_fields` in 8.10. We want to eventually deprecate use of this field as an array (in 8.10) in favor of the new object type. Utilizes the telemetry detections rule usage logic to add a new field `legacy_investigation_fields` - which is a total count of the number of rules utilizing the legacy `investigation_fields` (the field as an array). --- .../server/usage/collector.ts | 56 ++++ .../usage/detections/get_metrics.test.ts | 8 + .../detections/rules/get_initial_usage.ts | 8 + .../get_rule_object_correlations.ts | 1 + .../server/usage/detections/rules/types.ts | 2 + .../detections/rules/update_usage.test.ts | 107 ++++--- .../rules/usage_utils/update_query_usage.ts | 3 + .../rules/usage_utils/update_total_usage.ts | 3 + .../schema/xpack_plugins.json | 48 ++++ .../usage_collector/detection_rules.ts | 62 ++++ .../legacy_investigation_fields/data.json | 271 ++++++++++++++++++ 11 files changed, 530 insertions(+), 39 deletions(-) create mode 100644 x-pack/test/functional/es_archives/security_solution/legacy_investigation_fields/data.json diff --git a/x-pack/plugins/security_solution/server/usage/collector.ts b/x-pack/plugins/security_solution/server/usage/collector.ts index d458f280c5899..39635b9abda94 100644 --- a/x-pack/plugins/security_solution/server/usage/collector.ts +++ b/x-pack/plugins/security_solution/server/usage/collector.ts @@ -71,6 +71,13 @@ export const registerCollector: RegisterCollector = ({ type: 'long', _meta: { description: 'Number of notifications enabled' }, }, + legacy_investigation_fields: { + type: 'long', + _meta: { + description: + 'Number of rules using the legacy investigation fields type introduced only in 8.10 ESS', + }, + }, }, threshold: { enabled: { @@ -107,6 +114,13 @@ export const registerCollector: RegisterCollector = ({ type: 'long', _meta: { description: 'Number of notifications enabled' }, }, + legacy_investigation_fields: { + type: 'long', + _meta: { + description: + 'Number of rules using the legacy investigation fields type introduced only in 8.10 ESS', + }, + }, }, eql: { enabled: { type: 'long', _meta: { description: 'Number of eql rules enabled' } }, @@ -135,6 +149,13 @@ export const registerCollector: RegisterCollector = ({ type: 'long', _meta: { description: 'Number of notifications enabled' }, }, + legacy_investigation_fields: { + type: 'long', + _meta: { + description: + 'Number of rules using the legacy investigation fields type introduced only in 8.10 ESS', + }, + }, }, machine_learning: { enabled: { @@ -171,6 +192,13 @@ export const registerCollector: RegisterCollector = ({ type: 'long', _meta: { description: 'Number of notifications enabled' }, }, + legacy_investigation_fields: { + type: 'long', + _meta: { + description: + 'Number of rules using the legacy investigation fields type introduced only in 8.10 ESS', + }, + }, }, threat_match: { enabled: { @@ -207,6 +235,13 @@ export const registerCollector: RegisterCollector = ({ type: 'long', _meta: { description: 'Number of notifications enabled' }, }, + legacy_investigation_fields: { + type: 'long', + _meta: { + description: + 'Number of rules using the legacy investigation fields type introduced only in 8.10 ESS', + }, + }, }, new_terms: { enabled: { @@ -243,6 +278,13 @@ export const registerCollector: RegisterCollector = ({ type: 'long', _meta: { description: 'Number of notifications enabled' }, }, + legacy_investigation_fields: { + type: 'long', + _meta: { + description: + 'Number of rules using the legacy investigation fields type introduced only in 8.10 ESS', + }, + }, }, elastic_total: { enabled: { type: 'long', _meta: { description: 'Number of elastic rules enabled' } }, @@ -274,6 +316,13 @@ export const registerCollector: RegisterCollector = ({ type: 'long', _meta: { description: 'Number of notifications enabled' }, }, + legacy_investigation_fields: { + type: 'long', + _meta: { + description: + 'Number of rules using the legacy investigation fields type introduced only in 8.10 ESS', + }, + }, }, custom_total: { enabled: { type: 'long', _meta: { description: 'Number of custom rules enabled' } }, @@ -302,6 +351,13 @@ export const registerCollector: RegisterCollector = ({ type: 'long', _meta: { description: 'Number of notifications enabled' }, }, + legacy_investigation_fields: { + type: 'long', + _meta: { + description: + 'Number of rules using the legacy investigation fields type introduced only in 8.10 ESS', + }, + }, }, }, detection_rule_detail: { diff --git a/x-pack/plugins/security_solution/server/usage/detections/get_metrics.test.ts b/x-pack/plugins/security_solution/server/usage/detections/get_metrics.test.ts index afed10119756e..6c4d3c5a377d9 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/get_metrics.test.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/get_metrics.test.ts @@ -99,6 +99,7 @@ describe('Detections Usage and Metrics', () => { updated_on: '2021-03-23T17:15:59.634Z', has_legacy_notification: false, has_notification: false, + has_legacy_investigation_field: false, }, ], detection_rule_usage: { @@ -112,6 +113,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, elastic_total: { alerts: 3400, @@ -122,6 +124,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, }, }, @@ -163,6 +166,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, query: { alerts: 800, @@ -173,6 +177,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, }, }, @@ -217,6 +222,7 @@ describe('Detections Usage and Metrics', () => { updated_on: '2021-03-23T17:15:59.634Z', has_legacy_notification: false, has_notification: false, + has_legacy_investigation_field: false, }, ], detection_rule_usage: { @@ -230,6 +236,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, query: { alerts: 0, @@ -240,6 +247,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, }, }, diff --git a/x-pack/plugins/security_solution/server/usage/detections/rules/get_initial_usage.ts b/x-pack/plugins/security_solution/server/usage/detections/rules/get_initial_usage.ts index 3ad6b5740b53e..dfe19bff7079a 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/rules/get_initial_usage.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/rules/get_initial_usage.ts @@ -26,6 +26,7 @@ export const getInitialRulesUsage = (): RulesTypeUsage => ({ legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, threshold: { enabled: 0, @@ -36,6 +37,7 @@ export const getInitialRulesUsage = (): RulesTypeUsage => ({ legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, eql: { enabled: 0, @@ -46,6 +48,7 @@ export const getInitialRulesUsage = (): RulesTypeUsage => ({ legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, machine_learning: { enabled: 0, @@ -56,6 +59,7 @@ export const getInitialRulesUsage = (): RulesTypeUsage => ({ legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, threat_match: { enabled: 0, @@ -66,6 +70,7 @@ export const getInitialRulesUsage = (): RulesTypeUsage => ({ legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, new_terms: { enabled: 0, @@ -76,6 +81,7 @@ export const getInitialRulesUsage = (): RulesTypeUsage => ({ legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, elastic_total: { enabled: 0, @@ -86,6 +92,7 @@ export const getInitialRulesUsage = (): RulesTypeUsage => ({ legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, custom_total: { enabled: 0, @@ -96,6 +103,7 @@ export const getInitialRulesUsage = (): RulesTypeUsage => ({ legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, }); diff --git a/x-pack/plugins/security_solution/server/usage/detections/rules/transform_utils/get_rule_object_correlations.ts b/x-pack/plugins/security_solution/server/usage/detections/rules/transform_utils/get_rule_object_correlations.ts index 5387c63aace3e..116015b25db9d 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/rules/transform_utils/get_rule_object_correlations.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/rules/transform_utils/get_rule_object_correlations.ts @@ -55,6 +55,7 @@ export const getRuleObjectCorrelations = ({ cases_count_total: casesRuleIds.get(ruleId) || 0, has_legacy_notification: hasLegacyNotification, has_notification: hasNotification, + has_legacy_investigation_field: Array.isArray(attributes.params.investigationFields), }; }); }; diff --git a/x-pack/plugins/security_solution/server/usage/detections/rules/types.ts b/x-pack/plugins/security_solution/server/usage/detections/rules/types.ts index 84fb656f793d4..1bbe1b8f01f0e 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/rules/types.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/rules/types.ts @@ -14,6 +14,7 @@ export interface FeatureTypeUsage { legacy_notifications_disabled: number; notifications_enabled: number; notifications_disabled: number; + legacy_investigation_fields: number; } export interface RulesTypeUsage { @@ -46,6 +47,7 @@ export interface RuleMetric { cases_count_total: number; has_legacy_notification: boolean; has_notification: boolean; + has_legacy_investigation_field: boolean; } /** diff --git a/x-pack/plugins/security_solution/server/usage/detections/rules/update_usage.test.ts b/x-pack/plugins/security_solution/server/usage/detections/rules/update_usage.test.ts index b029d37e0082d..8bdb4c582f0ee 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/rules/update_usage.test.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/rules/update_usage.test.ts @@ -17,6 +17,7 @@ interface StubRuleOptions { caseCount: number; hasLegacyNotification: boolean; hasNotification: boolean; + hasLegacyInvestigationField: boolean; } const createStubRule = ({ @@ -27,6 +28,7 @@ const createStubRule = ({ caseCount, hasLegacyNotification, hasNotification, + hasLegacyInvestigationField, }: StubRuleOptions): RuleMetric => ({ rule_name: 'rule-name', rule_id: 'id-123', @@ -40,6 +42,7 @@ const createStubRule = ({ cases_count_total: caseCount, has_legacy_notification: hasLegacyNotification, has_notification: hasNotification, + has_legacy_investigation_field: hasLegacyInvestigationField, }); describe('Detections Usage and Metrics', () => { @@ -53,6 +56,7 @@ describe('Detections Usage and Metrics', () => { caseCount: 1, hasLegacyNotification: false, hasNotification: false, + hasLegacyInvestigationField: false, }); const usage = updateRuleUsage(stubRule, getInitialRulesUsage()); @@ -67,6 +71,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, eql: { alerts: 1, @@ -77,6 +82,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, }); }); @@ -90,6 +96,7 @@ describe('Detections Usage and Metrics', () => { caseCount: 1, hasLegacyNotification: false, hasNotification: false, + hasLegacyInvestigationField: false, }); const stubQueryRuleOne = createStubRule({ ruleType: 'query', @@ -99,6 +106,7 @@ describe('Detections Usage and Metrics', () => { caseCount: 2, hasLegacyNotification: false, hasNotification: false, + hasLegacyInvestigationField: true, }); const stubQueryRuleTwo = createStubRule({ ruleType: 'query', @@ -108,6 +116,7 @@ describe('Detections Usage and Metrics', () => { caseCount: 2, hasLegacyNotification: false, hasNotification: false, + hasLegacyInvestigationField: false, }); const stubMachineLearningOne = createStubRule({ ruleType: 'machine_learning', @@ -117,6 +126,7 @@ describe('Detections Usage and Metrics', () => { caseCount: 10, hasLegacyNotification: false, hasNotification: false, + hasLegacyInvestigationField: false, }); const stubMachineLearningTwo = createStubRule({ ruleType: 'machine_learning', @@ -126,6 +136,7 @@ describe('Detections Usage and Metrics', () => { caseCount: 44, hasLegacyNotification: false, hasNotification: false, + hasLegacyInvestigationField: false, }); let usage = updateRuleUsage(stubEqlRule, getInitialRulesUsage()); @@ -145,6 +156,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, elastic_total: { alerts: 28, @@ -155,6 +167,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 1, }, eql: { alerts: 1, @@ -165,6 +178,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, machine_learning: { alerts: 22, @@ -175,6 +189,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }, query: { alerts: 10, @@ -185,51 +200,58 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 1, }, }); }); - describe('table tests of "ruleType", "enabled", "elasticRule", and "legacyNotification"', () => { + describe('table tests of "ruleType", "enabled", "elasticRule", "legacyNotification", and "hasLegacyInvestigationField"', () => { test.each` - ruleType | enabled | hasLegacyNotification | hasNotification | expectedLegacyNotificationsEnabled | expectedLegacyNotificationsDisabled | expectedNotificationsEnabled | expectedNotificationsDisabled - ${'eql'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} - ${'eql'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'eql'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} - ${'eql'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'eql'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} - ${'eql'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} - ${'query'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} - ${'query'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'query'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} - ${'query'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'query'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} - ${'query'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} - ${'threshold'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} - ${'threshold'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'threshold'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} - ${'threshold'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'threshold'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} - ${'threshold'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} - ${'machine_learning'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} - ${'machine_learning'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'machine_learning'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} - ${'machine_learning'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'machine_learning'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} - ${'machine_learning'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} - ${'threat_match'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} - ${'threat_match'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'threat_match'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} - ${'threat_match'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'threat_match'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} - ${'threat_match'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} - ${'new_terms'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} - ${'new_terms'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'new_terms'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} - ${'new_terms'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} - ${'new_terms'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} - ${'new_terms'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} + ruleType | enabled | hasLegacyNotification | hasNotification | expectedLegacyNotificationsEnabled | expectedLegacyNotificationsDisabled | expectedNotificationsEnabled | expectedNotificationsDisabled | hasLegacyInvestigationField + ${'eql'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} | ${0} + ${'eql'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'eql'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} | ${0} + ${'eql'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'eql'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} | ${0} + ${'eql'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${0} + ${'eql'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${1} + ${'query'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} | ${0} + ${'query'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'query'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} | ${0} + ${'query'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'query'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} | ${0} + ${'query'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${0} + ${'query'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${1} + ${'threshold'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} | ${0} + ${'threshold'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'threshold'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} | ${0} + ${'threshold'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'threshold'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} | ${0} + ${'threshold'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${0} + ${'threshold'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${1} + ${'machine_learning'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} | ${0} + ${'machine_learning'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'machine_learning'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} | ${0} + ${'machine_learning'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'machine_learning'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} | ${0} + ${'machine_learning'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${0} + ${'machine_learning'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${1} + ${'threat_match'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} | ${0} + ${'threat_match'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'threat_match'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} | ${0} + ${'threat_match'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'threat_match'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} | ${0} + ${'threat_match'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${0} + ${'threat_match'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${1} + ${'new_terms'} | ${true} | ${true} | ${false} | ${1} | ${0} | ${0} | ${0} | ${0} + ${'new_terms'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'new_terms'} | ${false} | ${false} | ${true} | ${0} | ${0} | ${0} | ${1} | ${0} + ${'new_terms'} | ${true} | ${false} | ${true} | ${0} | ${0} | ${1} | ${0} | ${0} + ${'new_terms'} | ${false} | ${true} | ${false} | ${0} | ${1} | ${0} | ${0} | ${0} + ${'new_terms'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${0} + ${'new_terms'} | ${false} | ${false} | ${false} | ${0} | ${0} | ${0} | ${0} | ${1} `( - 'expect { "ruleType": $ruleType, "enabled": $enabled, "hasLegacyNotification": $hasLegacyNotification, "hasNotification": $hasNotification } to equal { legacy_notifications_enabled: $expectedLegacyNotificationsEnabled, legacy_notifications_disabled: $expectedLegacyNotificationsDisabled, notifications_enabled: $expectedNotificationsEnabled, notifications_disabled, $expectedNotificationsDisabled }', + 'expect { "ruleType": $ruleType, "enabled": $enabled, "hasLegacyNotification": $hasLegacyNotification, "hasNotification": $hasNotification, hasLegacyInvestigationField: $hasLegacyInvestigationField } to equal { legacy_notifications_enabled: $expectedLegacyNotificationsEnabled, legacy_notifications_disabled: $expectedLegacyNotificationsDisabled, notifications_enabled: $expectedNotificationsEnabled, notifications_disabled, $expectedNotificationsDisabled, hasLegacyInvestigationField: $hasLegacyInvestigationField }', ({ ruleType, enabled, @@ -239,6 +261,7 @@ describe('Detections Usage and Metrics', () => { expectedLegacyNotificationsDisabled, expectedNotificationsEnabled, expectedNotificationsDisabled, + hasLegacyInvestigationField, }) => { const rule1 = createStubRule({ ruleType, @@ -248,6 +271,7 @@ describe('Detections Usage and Metrics', () => { hasNotification, alertCount: 0, caseCount: 0, + hasLegacyInvestigationField, }); const usage = updateRuleUsage(rule1, getInitialRulesUsage()) as ReturnType< typeof updateRuleUsage @@ -258,6 +282,7 @@ describe('Detections Usage and Metrics', () => { legacy_notifications_disabled: expectedLegacyNotificationsDisabled, notifications_enabled: expectedNotificationsEnabled, notifications_disabled: expectedNotificationsDisabled, + legacy_investigation_fields: hasLegacyInvestigationField ? 1 : 0, }) ); @@ -270,6 +295,7 @@ describe('Detections Usage and Metrics', () => { hasNotification, alertCount: 0, caseCount: 0, + hasLegacyInvestigationField, }); const usageAddedByOne = updateRuleUsage(rule2, usage) as ReturnType< typeof updateRuleUsage @@ -289,6 +315,9 @@ describe('Detections Usage and Metrics', () => { expectedNotificationsEnabled !== 0 ? expectedNotificationsEnabled + 1 : 0, notifications_disabled: expectedNotificationsDisabled !== 0 ? expectedNotificationsDisabled + 1 : 0, + legacy_investigation_fields: hasLegacyInvestigationField + ? hasLegacyInvestigationField + 1 + : 0, }) ); } diff --git a/x-pack/plugins/security_solution/server/usage/detections/rules/usage_utils/update_query_usage.ts b/x-pack/plugins/security_solution/server/usage/detections/rules/usage_utils/update_query_usage.ts index 7f40ceec21c8a..e6c4e897b0b9b 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/rules/usage_utils/update_query_usage.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/rules/usage_utils/update_query_usage.ts @@ -44,5 +44,8 @@ export const updateQueryUsage = ({ notifications_disabled: notificationDisabled ? usage[ruleType].notifications_disabled + 1 : usage[ruleType].notifications_disabled, + legacy_investigation_fields: detectionRuleMetric.has_legacy_investigation_field + ? usage[ruleType].legacy_investigation_fields + 1 + : usage[ruleType].legacy_investigation_fields, }; }; diff --git a/x-pack/plugins/security_solution/server/usage/detections/rules/usage_utils/update_total_usage.ts b/x-pack/plugins/security_solution/server/usage/detections/rules/usage_utils/update_total_usage.ts index ed0ff37e2a328..3a63af1ce081a 100644 --- a/x-pack/plugins/security_solution/server/usage/detections/rules/usage_utils/update_total_usage.ts +++ b/x-pack/plugins/security_solution/server/usage/detections/rules/usage_utils/update_total_usage.ts @@ -47,5 +47,8 @@ export const updateTotalUsage = ({ notifications_disabled: notificationDisabled ? updatedUsage[totalType].notifications_disabled + 1 : updatedUsage[totalType].notifications_disabled, + legacy_investigation_fields: detectionRuleMetric.has_legacy_investigation_field + ? updatedUsage[totalType].legacy_investigation_fields + 1 + : updatedUsage[totalType].legacy_investigation_fields, }; }; diff --git a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json index abc8827e31ef7..e0d132b13648f 100644 --- a/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json +++ b/x-pack/plugins/telemetry_collection_xpack/schema/xpack_plugins.json @@ -12388,6 +12388,12 @@ "_meta": { "description": "Number of notifications enabled" } + }, + "legacy_investigation_fields": { + "type": "long", + "_meta": { + "description": "Number of rules using the legacy investigation fields type introduced only in 8.10 ESS" + } } } }, @@ -12440,6 +12446,12 @@ "_meta": { "description": "Number of notifications enabled" } + }, + "legacy_investigation_fields": { + "type": "long", + "_meta": { + "description": "Number of rules using the legacy investigation fields type introduced only in 8.10 ESS" + } } } }, @@ -12492,6 +12504,12 @@ "_meta": { "description": "Number of notifications enabled" } + }, + "legacy_investigation_fields": { + "type": "long", + "_meta": { + "description": "Number of rules using the legacy investigation fields type introduced only in 8.10 ESS" + } } } }, @@ -12544,6 +12562,12 @@ "_meta": { "description": "Number of notifications enabled" } + }, + "legacy_investigation_fields": { + "type": "long", + "_meta": { + "description": "Number of rules using the legacy investigation fields type introduced only in 8.10 ESS" + } } } }, @@ -12596,6 +12620,12 @@ "_meta": { "description": "Number of notifications enabled" } + }, + "legacy_investigation_fields": { + "type": "long", + "_meta": { + "description": "Number of rules using the legacy investigation fields type introduced only in 8.10 ESS" + } } } }, @@ -12648,6 +12678,12 @@ "_meta": { "description": "Number of notifications enabled" } + }, + "legacy_investigation_fields": { + "type": "long", + "_meta": { + "description": "Number of rules using the legacy investigation fields type introduced only in 8.10 ESS" + } } } }, @@ -12700,6 +12736,12 @@ "_meta": { "description": "Number of notifications enabled" } + }, + "legacy_investigation_fields": { + "type": "long", + "_meta": { + "description": "Number of rules using the legacy investigation fields type introduced only in 8.10 ESS" + } } } }, @@ -12752,6 +12794,12 @@ "_meta": { "description": "Number of notifications enabled" } + }, + "legacy_investigation_fields": { + "type": "long", + "_meta": { + "description": "Number of rules using the legacy investigation fields type introduced only in 8.10 ESS" + } } } } diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts index c913b8d6e8a68..73d377fa87f2d 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group4/telemetry/usage_collector/detection_rules.ts @@ -81,6 +81,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -89,6 +90,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -112,6 +114,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -121,6 +124,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -235,6 +239,44 @@ export default ({ getService }: FtrProviderContext) => { expect(stats.detection_rules.detection_rule_usage).to.eql(expected); }); }); + + describe('legacy investigation fields', () => { + before(async () => { + await esArchiver.load( + 'x-pack/test/functional/es_archives/security_solution/legacy_investigation_fields' + ); + }); + + after(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/legacy_investigation_fields' + ); + }); + + it('should show "legacy_investigation_fields" to be greater than 0 when a rule has "investigation_fields" set to array or empty array', async () => { + await retry.try(async () => { + const stats = await getStats(supertest, log); + const expected: RulesTypeUsage = { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage, + query: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.query, + alerts: 0, + enabled: 0, + disabled: 3, + legacy_investigation_fields: 2, + }, + custom_total: { + ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, + alerts: 0, + enabled: 0, + disabled: 3, + legacy_investigation_fields: 2, + }, + }; + expect(stats.detection_rules.detection_rule_usage).to.eql(expected); + }); + }); + }); }); describe('"eql" rule type', () => { @@ -283,6 +325,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -292,6 +335,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -428,6 +472,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -436,6 +481,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -465,6 +511,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -474,6 +521,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -629,6 +677,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -637,6 +686,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -657,6 +707,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -665,6 +716,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -787,6 +839,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -795,6 +848,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -833,6 +887,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, custom_total: { ...getInitialDetectionMetrics().detection_rules.detection_rule_usage.custom_total, @@ -842,6 +897,7 @@ export default ({ getService }: FtrProviderContext) => { notifications_disabled: 0, legacy_notifications_disabled: 0, legacy_notifications_enabled: 0, + legacy_investigation_fields: 0, }, }; expect(stats.detection_rules.detection_rule_usage).to.eql(expected); @@ -1016,6 +1072,7 @@ export default ({ getService }: FtrProviderContext) => { legacy_notifications_disabled: 0, notifications_enabled: 0, notifications_disabled: 0, + legacy_investigation_fields: 0, }); }); }); @@ -1046,6 +1103,7 @@ export default ({ getService }: FtrProviderContext) => { cases_count_total: 0, has_legacy_notification: false, has_notification: false, + has_legacy_investigation_field: false, }); }); }); @@ -1083,6 +1141,7 @@ export default ({ getService }: FtrProviderContext) => { cases_count_total: 0, has_notification: true, has_legacy_notification: false, + has_legacy_investigation_field: false, }); expect( stats.detection_rules.detection_rule_usage.elastic_total.notifications_disabled @@ -1135,6 +1194,7 @@ export default ({ getService }: FtrProviderContext) => { cases_count_total: 0, has_notification: true, has_legacy_notification: false, + has_legacy_investigation_field: false, }); expect( stats.detection_rules.detection_rule_usage.elastic_total.notifications_disabled @@ -1187,6 +1247,7 @@ export default ({ getService }: FtrProviderContext) => { cases_count_total: 0, has_notification: false, has_legacy_notification: true, + has_legacy_investigation_field: false, }); expect( stats.detection_rules.detection_rule_usage.elastic_total.notifications_disabled @@ -1239,6 +1300,7 @@ export default ({ getService }: FtrProviderContext) => { cases_count_total: 0, has_notification: false, has_legacy_notification: true, + has_legacy_investigation_field: false, }); expect( stats.detection_rules.detection_rule_usage.elastic_total.notifications_disabled diff --git a/x-pack/test/functional/es_archives/security_solution/legacy_investigation_fields/data.json b/x-pack/test/functional/es_archives/security_solution/legacy_investigation_fields/data.json new file mode 100644 index 0000000000000..f16c2d1a9f9d5 --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/legacy_investigation_fields/data.json @@ -0,0 +1,271 @@ +{ + "type": "doc", + "value": { + "index": ".kibana_alerting_cases", + "id": "alert:9095ee90-b075-11ec-bb3f-1f063f8e1234", + "source": { + "alert": { + "name":"Test investigation fields", + "tags":["migration"], + "alertTypeId": "siem.queryRule", + "consumer": "siem", + "revision": 0, + "params": { + "author": [], + "description": "a", + "ruleId": "2297be91-894c-4831-830f-b424a0ec84f0", + "falsePositives": [], + "from": "now-360s", + "immutable": false, + "license": "", + "outputIndex": "", + "investigationFields":["client.address","agent.name"], + "meta": { + "from": "1m", + "kibana_siem_app_url": "https://actions.kb.us-central1.gcp.cloud.es.io:9243/app/security" + }, + "maxSignals": 100, + "riskScore": 21, + "riskScoreMapping": [], + "severity": "low", + "severityMapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptionsList": [], + "type": "query", + "language": "kuery", + "index": [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*" + ], + "query": "*:*", + "filters": [] + }, + "schedule": { + "interval": "5m" + }, + "enabled": false, + "actions": [], + "throttle": null, + "notifyWhen": "onActiveAlert", + "apiKeyOwner": null, + "apiKey": null, + "createdBy": "1527796724", + "updatedBy": "1527796724", + "createdAt": "2022-03-30T22:05:53.511Z", + "updatedAt": "2022-03-30T22:05:53.511Z", + "muteAll": false, + "mutedInstanceIds": [], + "executionStatus": { + "status": "ok", + "lastExecutionDate": "2022-03-31T19:53:37.507Z", + "error": null, + "lastDuration": 2377 + }, + "meta": { + "versionApiKeyLastmodified": "8.10.0" + }, + "scheduledTaskId": null, + "legacyId": "9095ee90-b075-11ec-bb3f-1f063f8e0abc" + }, + "type": "alert", + "references": [], + "namespaces": [ + "default" + ], + "typeMigrationVersion": "8.10.0", + "coreMigrationVersion":"8.10.0", + "updated_at": "2022-03-31T19:53:39.885Z" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana_alerting_cases", + "id": "alert:9095ee90-b075-11ec-bb3f-1f063f8e5678", + "source": { + "alert": { + "name":"Test investigation fields empty array", + "tags":["migration"], + "alertTypeId": "siem.queryRule", + "consumer": "siem", + "revision": 0, + "params": { + "author": [], + "description": "a", + "ruleId": "2297be91-894c-4831-830f-b424a0ec5678", + "falsePositives": [], + "from": "now-360s", + "immutable": false, + "license": "", + "outputIndex": "", + "investigationFields":[], + "meta": { + "from": "1m", + "kibana_siem_app_url": "https://actions.kb.us-central1.gcp.cloud.es.io:9243/app/security" + }, + "maxSignals": 100, + "riskScore": 21, + "riskScoreMapping": [], + "severity": "low", + "severityMapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptionsList": [], + "type": "query", + "language": "kuery", + "index": [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*" + ], + "query": "*:*", + "filters": [] + }, + "schedule": { + "interval": "5m" + }, + "enabled": false, + "actions": [], + "throttle": null, + "notifyWhen": "onActiveAlert", + "apiKeyOwner": null, + "apiKey": null, + "createdBy": "1527796724", + "updatedBy": "1527796724", + "createdAt": "2022-03-30T22:05:53.511Z", + "updatedAt": "2022-03-30T22:05:53.511Z", + "muteAll": false, + "mutedInstanceIds": [], + "executionStatus": { + "status": "ok", + "lastExecutionDate": "2022-03-31T19:53:37.507Z", + "error": null, + "lastDuration": 2377 + }, + "meta": { + "versionApiKeyLastmodified": "8.10.0" + }, + "scheduledTaskId": null, + "legacyId": "9095ee90-b075-11ec-bb3f-1f063f8e0def" + }, + "type": "alert", + "references": [], + "namespaces": [ + "default" + ], + "typeMigrationVersion": "8.10.0", + "coreMigrationVersion":"8.10.0", + "updated_at": "2022-03-31T19:53:39.885Z" + } + } +} + +{ + "type": "doc", + "value": { + "index": ".kibana_alerting_cases", + "id": "alert:9095ee90-b075-11ec-bb3f-1f063f8e9102", + "source": { + "alert": { + "name":"Test investigation fields object", + "tags":["migration"], + "alertTypeId": "siem.queryRule", + "consumer": "siem", + "revision": 0, + "params": { + "author": [], + "description": "a", + "ruleId": "2297be91-894c-4831-830f-b424a0ec9102", + "falsePositives": [], + "from": "now-360s", + "immutable": false, + "license": "", + "outputIndex": "", + "investigationFields": { + "field_names": ["host.name"] + }, + "meta": { + "from": "1m", + "kibana_siem_app_url": "https://actions.kb.us-central1.gcp.cloud.es.io:9243/app/security" + }, + "maxSignals": 100, + "riskScore": 21, + "riskScoreMapping": [], + "severity": "low", + "severityMapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptionsList": [], + "type": "query", + "language": "kuery", + "index": [ + "apm-*-transaction*", + "traces-apm*", + "auditbeat-*", + "endgame-*", + "filebeat-*", + "logs-*", + "packetbeat-*", + "winlogbeat-*" + ], + "query": "*:*", + "filters": [] + }, + "schedule": { + "interval": "5m" + }, + "enabled": false, + "actions": [], + "throttle": null, + "notifyWhen": "onActiveAlert", + "apiKeyOwner": null, + "apiKey": null, + "createdBy": "1527796724", + "updatedBy": "1527796724", + "createdAt": "2022-03-30T22:05:53.511Z", + "updatedAt": "2022-03-30T22:05:53.511Z", + "muteAll": false, + "mutedInstanceIds": [], + "executionStatus": { + "status": "ok", + "lastExecutionDate": "2022-03-31T19:53:37.507Z", + "error": null, + "lastDuration": 2377 + }, + "meta": { + "versionApiKeyLastmodified": "8.11.0" + }, + "scheduledTaskId": null, + "legacyId": "9095ee90-b075-11ec-bb3f-1f063f8e0ghi" + }, + "type": "alert", + "references": [], + "namespaces": [ + "default" + ], + "typeMigrationVersion": "8.11.0", + "coreMigrationVersion":"8.11.0", + "updated_at": "2022-03-31T19:53:39.885Z" + } + } +} \ No newline at end of file