mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 01:13:23 -04:00
## Summary [Internal link](https://github.com/elastic/security-team/issues/10820) to the feature details Part of https://github.com/elastic/security-team/issues/11232 This PR covers SIEM Migrations Install API (route: `POST /internal/siem_migrations/rules/{migration_id}/install`) integration test: * install all installable custom migration rules * install all installable migration rules matched with prebuilt rules * install and enable all installable migration rules * install migration rules by ids * install rules of non-existing migration - nothing should be installed * Error handling: an error if body payload is not passed
This commit is contained in:
parent
0ae28aa8bc
commit
cd502acea1
4 changed files with 253 additions and 12 deletions
|
@ -10,6 +10,7 @@ export default function ({ loadTestFile }: FtrProviderContext) {
|
|||
describe('@ess SecuritySolution SIEM Migrations', () => {
|
||||
loadTestFile(require.resolve('./create'));
|
||||
loadTestFile(require.resolve('./get'));
|
||||
loadTestFile(require.resolve('./install'));
|
||||
loadTestFile(require.resolve('./stats'));
|
||||
loadTestFile(require.resolve('./update'));
|
||||
});
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* 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 expect from 'expect';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { ElasticRule } from '@kbn/security-solution-plugin/common/siem_migrations/model/rule_migration.gen';
|
||||
import { RuleTranslationResult } from '@kbn/security-solution-plugin/common/siem_migrations/constants';
|
||||
import { RuleResponse } from '@kbn/security-solution-plugin/common/api/detection_engine';
|
||||
import { deleteAllRules } from '../../../../../common/utils/security_solution';
|
||||
import {
|
||||
RuleMigrationDocument,
|
||||
createMigrationRules,
|
||||
defaultElasticRule,
|
||||
deleteAllMigrationRules,
|
||||
getMigrationRuleDocuments,
|
||||
migrationRulesRouteHelpersFactory,
|
||||
statsOverrideCallbackFactory,
|
||||
} from '../../utils';
|
||||
import { FtrProviderContext } from '../../../../ftr_provider_context';
|
||||
import {
|
||||
createPrebuiltRuleAssetSavedObjects,
|
||||
createRuleAssetSavedObject,
|
||||
deleteAllPrebuiltRuleAssets,
|
||||
deleteAllTimelines,
|
||||
} from '../../../detections_response/utils';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const es = getService('es');
|
||||
const log = getService('log');
|
||||
const supertest = getService('supertest');
|
||||
const securitySolutionApi = getService('securitySolutionApi');
|
||||
const migrationRulesRoutes = migrationRulesRouteHelpersFactory(supertest);
|
||||
|
||||
describe('@ess @serverless @serverlessQA Install API', () => {
|
||||
beforeEach(async () => {
|
||||
await deleteAllRules(supertest, log);
|
||||
await deleteAllTimelines(es, log);
|
||||
await deleteAllPrebuiltRuleAssets(es, log);
|
||||
await deleteAllMigrationRules(es);
|
||||
});
|
||||
|
||||
it('should install all installable custom migration rules', async () => {
|
||||
const migrationId = uuidv4();
|
||||
|
||||
const overrideCallback = (index: number): Partial<RuleMigrationDocument> => {
|
||||
const title = `Rule - ${index}`;
|
||||
const elasticRule = { ...defaultElasticRule, title };
|
||||
return {
|
||||
migration_id: migrationId,
|
||||
elastic_rule: elasticRule,
|
||||
translation_result: index < 2 ? RuleTranslationResult.FULL : undefined,
|
||||
};
|
||||
};
|
||||
|
||||
const migrationRuleDocuments = getMigrationRuleDocuments(5, overrideCallback);
|
||||
await createMigrationRules(es, migrationRuleDocuments);
|
||||
|
||||
const installResponse = await migrationRulesRoutes.install({ migrationId, payload: {} });
|
||||
expect(installResponse.body).toEqual({ installed: 2 });
|
||||
|
||||
// fetch installed migration rules information
|
||||
const response = await migrationRulesRoutes.get({ migrationId });
|
||||
const installedMigrationRules = response.body.data.reduce((acc, item) => {
|
||||
if (item.elastic_rule?.id) {
|
||||
acc.push(item.elastic_rule);
|
||||
}
|
||||
return acc;
|
||||
}, [] as ElasticRule[]);
|
||||
expect(installedMigrationRules.length).toEqual(2);
|
||||
|
||||
// fetch installed rules
|
||||
const { body: rulesResponse } = await securitySolutionApi
|
||||
.findRules({ query: {} })
|
||||
.expect(200);
|
||||
|
||||
const expectedRulesData = expect.arrayContaining(
|
||||
installedMigrationRules.map((migrationRule) =>
|
||||
expect.objectContaining({
|
||||
id: migrationRule.id,
|
||||
name: migrationRule.title,
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
expect(rulesResponse.data).toEqual(expectedRulesData);
|
||||
|
||||
// Installed rules should be disabled
|
||||
rulesResponse.data.forEach((rule: RuleResponse) => {
|
||||
expect(rule.enabled).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should install all installable migration rules matched with prebuilt rules', async () => {
|
||||
const ruleAssetSavedObject = createRuleAssetSavedObject({ rule_id: 'rule-1', version: 1 });
|
||||
await createPrebuiltRuleAssetSavedObjects(es, [ruleAssetSavedObject]);
|
||||
|
||||
const migrationId = uuidv4();
|
||||
|
||||
const overrideCallback = (index: number): Partial<RuleMigrationDocument> => {
|
||||
const { query_language: queryLanguage, query, ...rest } = defaultElasticRule;
|
||||
return {
|
||||
migration_id: migrationId,
|
||||
elastic_rule: index < 2 ? { ...rest, prebuilt_rule_id: 'rule-1' } : undefined,
|
||||
translation_result: index < 2 ? RuleTranslationResult.FULL : undefined,
|
||||
};
|
||||
};
|
||||
const migrationRuleDocuments = getMigrationRuleDocuments(4, overrideCallback);
|
||||
await createMigrationRules(es, migrationRuleDocuments);
|
||||
|
||||
const installResponse = await migrationRulesRoutes.install({ migrationId, payload: {} });
|
||||
expect(installResponse.body).toEqual({ installed: 2 });
|
||||
|
||||
// fetch installed rules
|
||||
const { body: rulesResponse } = await securitySolutionApi
|
||||
.findRules({ query: {} })
|
||||
.expect(200);
|
||||
|
||||
const expectedInstalledRules = expect.arrayContaining([
|
||||
expect.objectContaining(ruleAssetSavedObject['security-rule']),
|
||||
]);
|
||||
expect(rulesResponse.data.length).toEqual(1);
|
||||
expect(rulesResponse.data).toEqual(expectedInstalledRules);
|
||||
|
||||
// Installed rules should be disabled
|
||||
rulesResponse.data.forEach((rule: RuleResponse) => {
|
||||
expect(rule.enabled).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
it('should install and enable all installable migration rules', async () => {
|
||||
const migrationId = uuidv4();
|
||||
|
||||
const overrideCallback = statsOverrideCallbackFactory({
|
||||
migrationId,
|
||||
completed: 2,
|
||||
fullyTranslated: 2,
|
||||
});
|
||||
const migrationRuleDocuments = getMigrationRuleDocuments(2, overrideCallback);
|
||||
await createMigrationRules(es, migrationRuleDocuments);
|
||||
|
||||
const installResponse = await migrationRulesRoutes.install({
|
||||
migrationId,
|
||||
payload: { enabled: true },
|
||||
});
|
||||
expect(installResponse.body).toEqual({ installed: 2 });
|
||||
|
||||
// fetch installed rules
|
||||
const { body: rulesResponse } = await securitySolutionApi
|
||||
.findRules({ query: {} })
|
||||
.expect(200);
|
||||
|
||||
expect(rulesResponse.data.length).toEqual(2);
|
||||
|
||||
// Installed rules should be enabled
|
||||
rulesResponse.data.forEach((rule: RuleResponse) => {
|
||||
expect(rule.enabled).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should install migration rules by ids', async () => {
|
||||
const migrationId = uuidv4();
|
||||
|
||||
const overrideCallback = statsOverrideCallbackFactory({
|
||||
migrationId,
|
||||
completed: 5,
|
||||
fullyTranslated: 5,
|
||||
});
|
||||
const migrationRuleDocuments = getMigrationRuleDocuments(5, overrideCallback);
|
||||
const createdDocumentIds = await createMigrationRules(es, migrationRuleDocuments);
|
||||
|
||||
// Migration rules to install by ids
|
||||
const ids = createdDocumentIds.slice(0, 3);
|
||||
|
||||
const installResponse = await migrationRulesRoutes.install({
|
||||
migrationId,
|
||||
payload: { ids, enabled: true },
|
||||
});
|
||||
expect(installResponse.body).toEqual({ installed: 3 });
|
||||
|
||||
// fetch installed rules
|
||||
const { body: rulesResponse } = await securitySolutionApi
|
||||
.findRules({ query: {} })
|
||||
.expect(200);
|
||||
|
||||
expect(rulesResponse.data.length).toEqual(3);
|
||||
|
||||
// Installed rules should be enabled
|
||||
rulesResponse.data.forEach((rule: RuleResponse) => {
|
||||
expect(rule.enabled).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('should return zero installed rules as a response for the non-existing migration', async () => {
|
||||
const migrationId = uuidv4();
|
||||
const installResponse = await migrationRulesRoutes.install({ migrationId, payload: {} });
|
||||
expect(installResponse.body).toEqual({ installed: 0 });
|
||||
});
|
||||
|
||||
it('should return an error if body payload is not passed', async () => {
|
||||
const migrationId = uuidv4();
|
||||
const installResponse = await migrationRulesRoutes.install({
|
||||
migrationId,
|
||||
expectStatusCode: 400,
|
||||
});
|
||||
expect(installResponse.body).toEqual({
|
||||
statusCode: 400,
|
||||
error: 'Bad Request',
|
||||
message: '[request body]: Expected object, received null',
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -101,20 +101,20 @@ export const getMigrationRuleDocuments = (
|
|||
|
||||
export const statsOverrideCallbackFactory = ({
|
||||
migrationId,
|
||||
failed,
|
||||
pending,
|
||||
processing,
|
||||
completed,
|
||||
fullyTranslated,
|
||||
partiallyTranslated,
|
||||
failed = 0,
|
||||
pending = 0,
|
||||
processing = 0,
|
||||
completed = 0,
|
||||
fullyTranslated = 0,
|
||||
partiallyTranslated = 0,
|
||||
}: {
|
||||
migrationId: string;
|
||||
failed: number;
|
||||
pending: number;
|
||||
processing: number;
|
||||
completed: number;
|
||||
fullyTranslated: number;
|
||||
partiallyTranslated: number;
|
||||
failed?: number;
|
||||
pending?: number;
|
||||
processing?: number;
|
||||
completed?: number;
|
||||
fullyTranslated?: number;
|
||||
partiallyTranslated?: number;
|
||||
}) => {
|
||||
const overrideCallback = (index: number): Partial<RuleMigrationDocument> => {
|
||||
let translationResult;
|
||||
|
|
|
@ -15,6 +15,7 @@ import { replaceParams } from '@kbn/openapi-common/shared';
|
|||
import {
|
||||
SIEM_RULE_MIGRATIONS_ALL_STATS_PATH,
|
||||
SIEM_RULE_MIGRATIONS_PATH,
|
||||
SIEM_RULE_MIGRATION_INSTALL_PATH,
|
||||
SIEM_RULE_MIGRATION_PATH,
|
||||
SIEM_RULE_MIGRATION_STATS_PATH,
|
||||
SIEM_RULE_MIGRATION_TRANSLATION_STATS_PATH,
|
||||
|
@ -25,6 +26,7 @@ import {
|
|||
GetRuleMigrationRequestQuery,
|
||||
GetRuleMigrationResponse,
|
||||
GetRuleMigrationStatsResponse,
|
||||
InstallMigrationRulesResponse,
|
||||
UpdateRuleMigrationResponse,
|
||||
} from '@kbn/security-solution-plugin/common/siem_migrations/model/api/rules/rule_migration.gen';
|
||||
import { API_VERSIONS } from '@kbn/security-solution-plugin/common/constants';
|
||||
|
@ -58,6 +60,11 @@ export interface UpdateRulesParams extends MigrationRequestParams {
|
|||
payload?: any;
|
||||
}
|
||||
|
||||
export interface InstallRulesParams extends MigrationRequestParams {
|
||||
/** Optional payload to send */
|
||||
payload?: any;
|
||||
}
|
||||
|
||||
export const migrationRulesRouteHelpersFactory = (supertest: SuperTest.Agent) => {
|
||||
return {
|
||||
get: async ({
|
||||
|
@ -112,6 +119,23 @@ export const migrationRulesRouteHelpersFactory = (supertest: SuperTest.Agent) =>
|
|||
return response;
|
||||
},
|
||||
|
||||
install: async ({
|
||||
migrationId,
|
||||
payload,
|
||||
expectStatusCode = 200,
|
||||
}: InstallRulesParams): Promise<{ body: InstallMigrationRulesResponse }> => {
|
||||
const response = await supertest
|
||||
.post(replaceParams(SIEM_RULE_MIGRATION_INSTALL_PATH, { migration_id: migrationId }))
|
||||
.set('kbn-xsrf', 'true')
|
||||
.set(ELASTIC_HTTP_VERSION_HEADER, API_VERSIONS.internal.v1)
|
||||
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
|
||||
.send(payload);
|
||||
|
||||
assertStatusCode(expectStatusCode, response);
|
||||
|
||||
return response;
|
||||
},
|
||||
|
||||
stats: async ({
|
||||
migrationId,
|
||||
expectStatusCode = 200,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue