Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Entity Analytics] Simplify telemetry tests, add empty index check and logging #183915

Merged
merged 8 commits into from
May 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -16,6 +16,7 @@ import {
riskEngineRouteHelpersFactory,
cleanRiskEngine,
getRiskEngineStats,
areRiskScoreIndicesEmpty,
} from '../../utils';
import { FtrProviderContext } from '../../../../ftr_provider_context';

Expand All @@ -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);

Expand All @@ -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 () => {
Expand All @@ -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 });
hop-dev marked this conversation as resolved.
Show resolved Hide resolved
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);
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,52 @@ export const deleteRiskScoreIndices = async ({
}
};

export const areRiskScoreIndicesEmpty = async ({
es,
namespace = 'default',
log,
}: {
es: Client;
namespace?: string;
log: ToolingLog;
}): Promise<boolean> => {
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
Expand Down