Skip to content

Commit

Permalink
implements tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dplumlee committed Sep 30, 2024
1 parent 34f4e7d commit d44453a
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 43 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import {
kqlQueryDiffAlgorithm,
eqlQueryDiffAlgorithm,
esqlQueryDiffAlgorithm,
ruleTypeDiffAlgorithm,
} from './algorithms';

const BASE_TYPE_ERROR = `Base version can't be of different rule type`;
Expand Down Expand Up @@ -212,7 +213,7 @@ const calculateCustomQueryFieldsDiff = (
};

const customQueryFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableCustomQueryFields> = {
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
kql_query: kqlQueryDiffAlgorithm,
data_source: dataSourceDiffAlgorithm,
alert_suppression: simpleDiffAlgorithm,
Expand All @@ -225,7 +226,7 @@ const calculateSavedQueryFieldsDiff = (
};

const savedQueryFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableSavedQueryFields> = {
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
kql_query: kqlQueryDiffAlgorithm,
data_source: dataSourceDiffAlgorithm,
alert_suppression: simpleDiffAlgorithm,
Expand All @@ -238,7 +239,7 @@ const calculateEqlFieldsDiff = (
};

const eqlFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableEqlFields> = {
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
eql_query: eqlQueryDiffAlgorithm,
data_source: dataSourceDiffAlgorithm,
event_category_override: singleLineStringDiffAlgorithm,
Expand All @@ -254,7 +255,7 @@ const calculateEsqlFieldsDiff = (
};

const esqlFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableEsqlFields> = {
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
esql_query: esqlQueryDiffAlgorithm,
alert_suppression: simpleDiffAlgorithm,
};
Expand All @@ -266,7 +267,7 @@ const calculateThreatMatchFieldsDiff = (
};

const threatMatchFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableThreatMatchFields> = {
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
kql_query: kqlQueryDiffAlgorithm,
data_source: dataSourceDiffAlgorithm,
threat_query: kqlQueryDiffAlgorithm,
Expand All @@ -284,7 +285,7 @@ const calculateThresholdFieldsDiff = (
};

const thresholdFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableThresholdFields> = {
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
kql_query: kqlQueryDiffAlgorithm,
data_source: dataSourceDiffAlgorithm,
threshold: simpleDiffAlgorithm,
Expand All @@ -299,7 +300,7 @@ const calculateMachineLearningFieldsDiff = (

const machineLearningFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableMachineLearningFields> =
{
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
machine_learning_job_id: simpleDiffAlgorithm,
anomaly_threshold: numberDiffAlgorithm,
alert_suppression: simpleDiffAlgorithm,
Expand All @@ -312,7 +313,7 @@ const calculateNewTermsFieldsDiff = (
};

const newTermsFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableNewTermsFields> = {
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
kql_query: kqlQueryDiffAlgorithm,
data_source: dataSourceDiffAlgorithm,
new_terms_fields: scalarArrayDiffAlgorithm,
Expand All @@ -336,5 +337,5 @@ const allFieldsDiffAlgorithms: FieldsDiffAlgorithmsFor<DiffableAllFields> = {
...thresholdFieldsDiffAlgorithms,
...machineLearningFieldsDiffAlgorithms,
...newTermsFieldsDiffAlgorithms,
type: simpleDiffAlgorithm,
type: ruleTypeDiffAlgorithm,
};
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
*/
import expect from 'expect';
import {
RuleUpdateProps,
ThreeWayDiffConflict,
ThreeWayDiffOutcome,
ThreeWayMergeOutcome,
} from '@kbn/security-solution-plugin/common/api/detection_engine';
import { getPrebuiltRuleMock } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules/mocks';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
import {
deleteAllTimelines,
Expand All @@ -20,6 +22,7 @@ import {
reviewPrebuiltRulesToUpgrade,
patchRule,
createHistoricalPrebuiltRuleAssetSavedObjects,
updateRule,
} from '../../../../utils';
import { deleteAllRules } from '../../../../../../../common/utils/security_solution';

Expand Down Expand Up @@ -59,7 +62,7 @@ export default ({ getService }: FtrProviderContext): void => {
// Call the upgrade review prebuilt rules endpoint and check that there is 1 rule eligible for update
// but type field is NOT returned
const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest);
expect(reviewResponse.rules[0].diff.fields.name).toBeUndefined();
expect(reviewResponse.rules[0].diff.fields.type).toBeUndefined();

expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1);
expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(0);
Expand All @@ -78,10 +81,15 @@ export default ({ getService }: FtrProviderContext): void => {
await installPrebuiltRules(es, supertest);

// Customize a type field on the installed rule
await patchRule(supertest, log, {
await updateRule(supertest, {
...getPrebuiltRuleMock(),
rule_id: 'rule-1',
type: 'eql',
});
type: 'saved_query',
query: undefined,
language: undefined,
filters: undefined,
saved_id: 'saved-query-id',
} as RuleUpdateProps);

// Increment the version of the installed rule, do NOT update the related type field, and create the new rule assets
const updatedRuleAssetSavedObjects = [
Expand All @@ -96,9 +104,9 @@ export default ({ getService }: FtrProviderContext): void => {
// Call the upgrade review prebuilt rules endpoint and check that type diff field
// is returned but field does not have an update, and the merge outcome is "Target"
const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest);
expect(reviewResponse.rules[0].diff.fields.name).toEqual({
expect(reviewResponse.rules[0].diff.fields.type).toEqual({
base_version: 'query',
current_version: 'eql',
current_version: 'saved_query',
target_version: 'query',
merged_version: 'query',
diff_outcome: ThreeWayDiffOutcome.CustomizedValueNoUpdate,
Expand Down Expand Up @@ -129,26 +137,27 @@ export default ({ getService }: FtrProviderContext): void => {
createRuleAssetSavedObject({
rule_id: 'rule-1',
version: 2,
type: 'eql',
type: 'saved_query',
saved_id: 'even-newer-saved-query-id',
}),
];
await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects);

// Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update
const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest);
expect(reviewResponse.rules[0].diff.fields.name).toEqual({
expect(reviewResponse.rules[0].diff.fields.type).toEqual({
base_version: 'query',
current_version: 'query',
target_version: 'eql',
merged_version: 'eql',
target_version: 'saved_query',
merged_version: 'saved_query',
diff_outcome: ThreeWayDiffOutcome.StockValueCanUpdate,
merge_outcome: ThreeWayMergeOutcome.Target,
conflict: ThreeWayDiffConflict.NON_SOLVABLE,
has_update: true,
has_base_version: true,
});

expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2);
expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(3); // version and query fields also have updates
expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1);
expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1);

Expand All @@ -165,28 +174,34 @@ export default ({ getService }: FtrProviderContext): void => {
await installPrebuiltRules(es, supertest);

// Customize a type field on the installed rule
await patchRule(supertest, log, {
await updateRule(supertest, {
...getPrebuiltRuleMock(),
rule_id: 'rule-1',
type: 'eql',
});
type: 'saved_query',
query: undefined,
language: undefined,
filters: undefined,
saved_id: 'saved-query-id',
} as RuleUpdateProps);

// Increment the version of the installed rule, update a type field, and create the new rule assets
const updatedRuleAssetSavedObjects = [
createRuleAssetSavedObject({
rule_id: 'rule-1',
version: 2,
type: 'eql',
type: 'saved_query',
saved_id: 'saved-query-id',
}),
];
await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects);

// Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update
const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest);
expect(reviewResponse.rules[0].diff.fields.name).toEqual({
expect(reviewResponse.rules[0].diff.fields.type).toEqual({
base_version: 'query',
current_version: 'eql',
target_version: 'eql',
merged_version: 'eql',
current_version: 'saved_query',
target_version: 'saved_query',
merged_version: 'saved_query',
diff_outcome: ThreeWayDiffOutcome.CustomizedValueSameUpdate,
merge_outcome: ThreeWayMergeOutcome.Target,
conflict: ThreeWayDiffConflict.NON_SOLVABLE,
Expand All @@ -211,27 +226,33 @@ export default ({ getService }: FtrProviderContext): void => {
await installPrebuiltRules(es, supertest);

// Customize a type field on the installed rule
await patchRule(supertest, log, {
await updateRule(supertest, {
...getPrebuiltRuleMock(),
rule_id: 'rule-1',
type: 'eql',
});
type: 'saved_query',
query: undefined,
language: undefined,
filters: undefined,
saved_id: 'saved-query-id',
} as RuleUpdateProps);

// Increment the version of the installed rule, update a type field, and create the new rule assets
const updatedRuleAssetSavedObjects = [
createRuleAssetSavedObject({
rule_id: 'rule-1',
version: 2,
type: 'esql',
language: 'esql',
}),
];
await createHistoricalPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects);

// Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update
// and type field update has NON_SOLVABLE conflict, and merged version is TARGET
const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest);
expect(reviewResponse.rules[0].diff.fields.name).toEqual({
expect(reviewResponse.rules[0].diff.fields.type).toEqual({
base_version: 'query',
current_version: 'eql',
current_version: 'saved_query',
target_version: 'esql',
merged_version: 'esql',
diff_outcome: ThreeWayDiffOutcome.CustomizedValueCanUpdate,
Expand All @@ -241,9 +262,9 @@ export default ({ getService }: FtrProviderContext): void => {
has_base_version: true,
});

expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2);
expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1);
expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1);
expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(4); // version + type + kql_query all considered updates
expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(2); // type + kql_query both considered conflicts
expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(2);

expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1);
expect(reviewResponse.stats.num_rules_with_conflicts).toBe(1);
Expand Down Expand Up @@ -274,7 +295,7 @@ export default ({ getService }: FtrProviderContext): void => {
// Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update
// but does NOT contain type field
const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest);
expect(reviewResponse.rules[0].diff.fields.name).toBeUndefined();
expect(reviewResponse.rules[0].diff.fields.type).toBeUndefined();

expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(1);
expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(1); // version is considered a conflict
Expand Down Expand Up @@ -306,27 +327,28 @@ export default ({ getService }: FtrProviderContext): void => {
createRuleAssetSavedObject({
rule_id: 'rule-1',
version: 2,
type: 'eql',
type: 'saved_query',
saved_id: 'saved-query-id',
}),
];
await createPrebuiltRuleAssetSavedObjects(es, updatedRuleAssetSavedObjects);

// Call the upgrade review prebuilt rules endpoint and check that one rule is eligible for update
// and type field update does not have a conflict
const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest);
expect(reviewResponse.rules[0].diff.fields.name).toEqual({
expect(reviewResponse.rules[0].diff.fields.type).toEqual({
current_version: 'query',
target_version: 'eql',
merged_version: 'eql',
target_version: 'saved_query',
merged_version: 'saved_query',
diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate,
merge_outcome: ThreeWayMergeOutcome.Target,
conflict: ThreeWayDiffConflict.NON_SOLVABLE,
has_update: true,
has_base_version: false,
});

expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(2);
expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(2); // type + version are both considered conflicts
expect(reviewResponse.rules[0].diff.num_fields_with_updates).toBe(3);
expect(reviewResponse.rules[0].diff.num_fields_with_conflicts).toBe(3); // type + version + query are all considered conflicts
expect(reviewResponse.rules[0].diff.num_fields_with_non_solvable_conflicts).toBe(1);

expect(reviewResponse.stats.num_rules_to_upgrade_total).toBe(1);
Expand Down

0 comments on commit d44453a

Please sign in to comment.