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

[8.16] [Security Solution] Fix `DataSource` payload creation during rule upgrade with `MERGED` pick_version (#197262) #197466

Merged
merged 1 commit into from
Oct 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 @@ -7,6 +7,8 @@
import { get } from 'lodash';
import type {
RuleSchedule,
DataSourceIndexPatterns,
DataSourceDataView,
InlineKqlQuery,
ThreeWayDiff,
DiffableRuleTypes,
Expand Down Expand Up @@ -195,6 +197,10 @@ export const transformDiffableFieldValues = (
} else if (fieldName === 'saved_id' && isInlineQuery(diffableFieldValue)) {
// saved_id should be set only for rules with SavedKqlQuery, undefined otherwise
return { type: 'TRANSFORMED_FIELD', value: undefined };
} else if (fieldName === 'data_view_id' && isDataSourceIndexPatterns(diffableFieldValue)) {
return { type: 'TRANSFORMED_FIELD', value: undefined };
} else if (fieldName === 'index' && isDataSourceDataView(diffableFieldValue)) {
return { type: 'TRANSFORMED_FIELD', value: undefined };
}

return { type: 'NON_TRANSFORMED_FIELD' };
Expand All @@ -209,3 +215,18 @@ function isInlineQuery(value: unknown): value is InlineKqlQuery {
typeof value === 'object' && value !== null && 'type' in value && value.type === 'inline_query'
);
}

function isDataSourceIndexPatterns(value: unknown): value is DataSourceIndexPatterns {
return (
typeof value === 'object' &&
value !== null &&
'type' in value &&
value.type === 'index_patterns'
);
}

function isDataSourceDataView(value: unknown): value is DataSourceDataView {
return (
typeof value === 'object' && value !== null && 'type' in value && value.type === 'data_view'
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import {
ThreatMatchRule,
FIELDS_TO_UPGRADE_TO_CURRENT_VERSION,
ModeEnum,
AllFieldsDiff,
DataSourceIndexPatterns,
QueryRule,
} from '@kbn/security-solution-plugin/common/api/detection_engine';
import { PrebuiltRuleAsset } from '@kbn/security-solution-plugin/server/lib/detection_engine/prebuilt_rules';
import { FtrProviderContext } from '../../../../../../ftr_provider_context';
Expand Down Expand Up @@ -246,6 +249,41 @@ export default ({ getService }: FtrProviderContext): void => {
expect(installedRule.tags).toEqual(reviewRuleResponseMap.get(ruleId)?.tags);
}
});

it('correctly upgrades rules with DataSource diffs to their MERGED versions', async () => {
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [queryRule]);
await installPrebuiltRules(es, supertest);

const targetObject = cloneDeep(queryRule);
targetObject['security-rule'].version += 1;
targetObject['security-rule'].name = TARGET_NAME;
targetObject['security-rule'].tags = TARGET_TAGS;
targetObject['security-rule'].index = ['auditbeat-*'];
await createHistoricalPrebuiltRuleAssetSavedObjects(es, [targetObject]);

const reviewResponse = await reviewPrebuiltRulesToUpgrade(supertest);
const ruleDiffFields = reviewResponse.rules[0].diff.fields as AllFieldsDiff;

const performUpgradeResponse = await performUpgradePrebuiltRules(es, supertest, {
mode: ModeEnum.ALL_RULES,
pick_version: 'MERGED',
});

expect(performUpgradeResponse.summary.succeeded).toEqual(1);

const installedRules = await getInstalledRules(supertest);
const installedRule = installedRules.data[0] as QueryRule;

expect(installedRule.name).toEqual(ruleDiffFields.name.merged_version);
expect(installedRule.tags).toEqual(ruleDiffFields.tags.merged_version);

// Check that the updated rules has an `index` field which equals the output of the diff algorithm
// for the DataSource diffable field, and that the data_view_id is correspondingly set to undefined.
expect(installedRule.index).toEqual(
(ruleDiffFields.data_source.merged_version as DataSourceIndexPatterns).index_patterns
);
expect(installedRule.data_view_id).toBe(undefined);
});
});

describe('edge cases and unhappy paths', () => {
Expand Down