From b6e0f87900067d7ef6f69206a36226aee595867e Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Thu, 23 May 2024 08:53:25 +0100 Subject: [PATCH] [Entity Analytics] Simplify telemetry tests, add empty index check and logging (#183915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Closes https://github.com/elastic/kibana/issues/182881 Not sure what went wrong with this test btu I did find the structure slightly more complicated than needed, I have moved the beforeEach data loading into the test body and removed the describe blocks. I have also removed the afterEach, we really shouldnt need to delete the data twice 😓 I have done [a 200 flaky test run](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6059#018f9b55-2231-4655-ab35-c6f26aa49720) 🟠 173 succeeded and 2 failed due to a bootstrap issue which caused the others not to run. --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../telemetry_usage.ts | 114 ++++++++---------- .../entity_analytics/utils/risk_engine.ts | 46 +++++++ 2 files changed, 96 insertions(+), 64 deletions(-) diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/telemetry_usage.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/telemetry_usage.ts index 1c3b1349a6289..3eca71c37dab5 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/telemetry_usage.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/risk_engine/trial_license_complete_tier/telemetry_usage.ts @@ -16,6 +16,7 @@ import { riskEngineRouteHelpersFactory, cleanRiskEngine, getRiskEngineStats, + areRiskScoreIndicesEmpty, } from '../../utils'; import { FtrProviderContext } from '../../../../ftr_provider_context'; @@ -25,7 +26,6 @@ export default ({ getService }: FtrProviderContext) => { const log = getService('log'); const retry = getService('retry'); const es = getService('es'); - const createAndSyncRuleAndAlerts = createAndSyncRuleAndAlertsFactory({ supertest, log }); const riskEngineRoutes = riskEngineRouteHelpersFactory(supertest); @@ -43,6 +43,9 @@ export default ({ getService }: FtrProviderContext) => { after(async () => { await esArchiver.unload('x-pack/test/functional/es_archives/security_solution/ecs_compliant'); + await cleanRiskEngine({ kibanaServer, es, log }); + await deleteAllAlerts(supertest, log, es); + await deleteAllRules(supertest, log); }); beforeEach(async () => { @@ -51,79 +54,62 @@ export default ({ getService }: FtrProviderContext) => { await deleteAllRules(supertest, log); }); - describe('Risk engine not enabled', () => { - it('should has empty riskEngineMetrics', async () => { - await retry.try(async () => { - const stats = await getRiskEngineStats(supertest, log); - const expected = {}; - expect(stats).to.eql(expected); - }); + it('should return empty metrics when the risk engine is disabled', async () => { + await retry.try(async () => { + const stats = await getRiskEngineStats(supertest, log); + expect(stats).to.eql({}); }); }); - describe('Risk engine enabled', () => { - let hostId: string; - let userId: string; + // https://github.com/elastic/kibana/issues/183246 + it('@skipInServerlessMKI should return metrics with expected values when risk engine is enabled', async () => { + expect(await areRiskScoreIndicesEmpty({ log, es })).to.be(true); - beforeEach(async () => { - hostId = uuidv4(); - const hostEvent = buildDocument({ host: { name: 'host-1' } }, hostId); - await indexListOfDocuments( - Array(10) - .fill(hostEvent) - .map((event, index) => ({ - ...event, - 'host.name': `host-${index}`, - })) - ); + const hostId = uuidv4(); + const hostDocs = Array(10) + .fill(buildDocument({}, hostId)) + .map((event, index) => ({ + ...event, + 'host.name': `host-${index}`, + })); - userId = uuidv4(); - const userEvent = buildDocument({ user: { name: 'user-1' } }, userId); - await indexListOfDocuments( - Array(10) - .fill(userEvent) - .map((event, index) => ({ - ...event, - 'user.name': `user-${index}`, - })) - ); + const userId = uuidv4(); + const userDocs = Array(10) + .fill(buildDocument({}, userId)) + .map((event, index) => ({ + ...event, + 'user.name': `user-${index}`, + })); - await createAndSyncRuleAndAlerts({ - query: `id: ${userId} or id: ${hostId}`, - alerts: 20, - riskScore: 40, - }); + await indexListOfDocuments([...hostDocs, ...userDocs]); - await riskEngineRoutes.init(); + await createAndSyncRuleAndAlerts({ + query: `id: ${userId} or id: ${hostId}`, + alerts: 20, + riskScore: 40, }); - afterEach(async () => { - await cleanRiskEngine({ kibanaServer, es, log }); - await deleteAllAlerts(supertest, log, es); - await deleteAllRules(supertest, log); - }); + await riskEngineRoutes.init(); + + await waitForRiskScoresToBePresent({ es, log, scoreCount: 20 }); - // https://github.com/elastic/kibana/issues/183246 - it('@skipInServerlessMKI should return riskEngineMetrics with expected values', async () => { - await waitForRiskScoresToBePresent({ es, log, scoreCount: 20 }); - await retry.try(async () => { - const { - all_risk_scores_index_size: allRiskScoreIndexSize, - unique_risk_scores_index_size: uniqueRiskScoreIndexSize, - ...otherStats - } = await getRiskEngineStats(supertest, log); - const expected = { - unique_host_risk_score_total: 0, - unique_user_risk_score_total: 0, - unique_user_risk_score_day: 0, - unique_host_risk_score_day: 0, - all_user_risk_scores_total: 10, - all_host_risk_scores_total: 10, - all_user_risk_scores_total_day: 10, - all_host_risk_scores_total_day: 10, - }; - expect(otherStats).to.eql(expected); - }); + await retry.try(async () => { + const { + all_risk_scores_index_size: allRiskScoreIndexSize, + unique_risk_scores_index_size: uniqueRiskScoreIndexSize, + ...otherStats + } = await getRiskEngineStats(supertest, log); + const expected = { + unique_host_risk_score_total: 0, + unique_user_risk_score_total: 0, + unique_user_risk_score_day: 0, + unique_host_risk_score_day: 0, + all_user_risk_scores_total: 10, + all_host_risk_scores_total: 10, + all_user_risk_scores_total_day: 10, + all_host_risk_scores_total_day: 10, + }; + expect(otherStats).to.eql(expected); }); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts index dbd4ed78c1896..4c39cdce1a48a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/risk_engine.ts @@ -148,6 +148,52 @@ export const deleteRiskScoreIndices = async ({ } }; +export const areRiskScoreIndicesEmpty = async ({ + es, + namespace = 'default', + log, +}: { + es: Client; + namespace?: string; + log: ToolingLog; +}): Promise => { + const riskScoreIndex = `risk-score.risk-score-${namespace}`; + const riskScoreLatestIndex = `risk-score.risk-score-latest-${namespace}`; + let riskScoreCount = 0; + let riskScoreLatestCount = 0; + + try { + const [riskScoreCountRes, riskScoreLatestCountRes] = await Promise.all([ + es.count({ index: riskScoreIndex }), + es.count({ index: riskScoreLatestIndex }), + ]); + riskScoreCount = riskScoreCountRes.count; + riskScoreLatestCount = riskScoreLatestCountRes.count; + } catch (e) { + if (e.meta.statusCode === 404) { + return true; + } + throw e; + } + + const isEmpty = riskScoreCount === 0 && riskScoreLatestCount === 0; + + if (!isEmpty) { + log.warning( + `Risk score indices are not empty. Risk score index count: ${riskScoreCount}, Risk score latest index count: ${riskScoreLatestCount}` + ); + const [riskScoreDocs, riskScoreLatestDocs] = await Promise.all([ + es.search({ index: riskScoreIndex, size: 25 }), + es.search({ index: riskScoreLatestIndex, size: 25 }), + ]); + + log.info(`Risk score index documents: ${JSON.stringify(riskScoreDocs.hits.hits)}`); + log.info(`Risk score latest index documents: ${JSON.stringify(riskScoreLatestDocs.hits.hits)}`); + } + + return isEmpty; +}; + /** * Deletes all risk scores from a given index or indices, defaults to `risk-score.risk-score-*` * For use inside of afterEach blocks of tests