-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Security Solution] Add UI incentivizers to upgrade prebuilt rules #211862
base: main
Are you sure you want to change the base?
[Security Solution] Add UI incentivizers to upgrade prebuilt rules #211862
Conversation
…-version-handling
…-version-handling
…-version-handling
c33ab5b
to
0aed247
Compare
Pinging @elastic/security-detections-response (Team:Detections and Resp) |
Pinging @elastic/security-solution (Team: SecuritySolution) |
Pinging @elastic/security-detection-rule-management (Team:Detection Rule Management) |
Files by Code Ownerelastic/security-detection-engine
elastic/security-detection-rule-management
elastic/security-engineering-productivity
elastic/security-solution
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dplumlee Thanks for improving UX for prebuilt rules with missing base version 🙏
I reviewed the changes and tested them locally. Testing didn't reveal issues.
I left a number of comments though critical are the following
- Revert rate limiting retry logic
- rename
hasBaseVersion
tohas_base_version
in the API contract - double check diff algorithms implementation changes are correct. The task ticket assumes we merge the changes for non-functional fields but the implementation does't do that for fields like
description
,note
,setup
.
On top of that I have some general comments not directly related to that PR.
Changes to diff algorithms might be much simpler if the functionality was implemented via Strategy pattern. We have a lot similar logic for each field with some specific details. Missing base version case isn't exception.
@@ -172,7 +175,20 @@ const EditRulePageComponent: FC<{ rule: RuleResponse }> = ({ rule }) => { | |||
newTermsFields: defineStepData.newTermsFields, | |||
}); | |||
|
|||
const loading = userInfoLoading || listsConfigLoading; | |||
const { upgradeReviewResponse, isLoading: isRuleUpgradeReviewLoading } = usePrebuiltRulesUpgrade({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: It could be extracted to usePrebuiltRuleUpgradeById()
hook accepting a rule id. Additionally isRuleUpgradeable
calculation could be included in that hook.
@@ -89,4 +89,5 @@ export interface RuleUpgradeInfoForReview { | |||
target_rule: RuleResponse; | |||
diff: PartialRuleDiff; | |||
revision: number; | |||
hasBaseVersion: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We stick to snake case in API contracts
hasBaseVersion: boolean; | |
has_base_version: boolean; |
The other comment we could address later regarding has_base_version
at this level.
Fields Diff includes has_base_version
in each field diff response. It looks like overkill since rule either has a base version or not and it's sufficient to have a single has_base_version
at the rule level. It means fields diff level has_base_version
should be removed.
...ection_engine/rule_management_ui/components/rule_update_callouts/has_rule_update_callout.tsx
Outdated
Show resolved
Hide resolved
...ne/rule_management/api/hooks/prebuilt_rules/use_fetch_prebuilt_rules_install_review_query.ts
Outdated
Show resolved
Hide resolved
@@ -48,6 +48,7 @@ export const RuleUpgrade = memo(function RuleUpgrade({ | |||
<RuleUpgradeCallout | |||
numOfSolvableConflicts={numOfSolvableConflicts} | |||
numOfNonSolvableConflicts={numOfNonSolvableConflicts} | |||
hasBaseVersion={ruleUpgradeState.hasBaseVersion} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should missing base version callout logic is placed in RuleUpgradeCallout
? It feels simple to place a component named like RuleHasMissingBaseVersionCallout
component on top of RuleUpgradeCallout
.
@@ -421,81 +421,162 @@ describe('dataSourceDiffAlgorithm', () => { | |||
}); | |||
|
|||
describe('if base_version is missing', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
describe('if base_version is missing', () => { | |
describe('when base_version is missing', () => { |
|
||
describe('returns target_version as merged output if current_version and target_version are different - scenario -AB', () => { | ||
it('if versions are different types', () => { | ||
describe('if current_version and target_version are the same - scenario -AA', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
describe('if current_version and target_version are the same - scenario -AA', () => { | |
describe('and current and target rule versions are the same - scenario -AA', () => { |
}) | ||
); | ||
}); | ||
}); | ||
|
||
describe('if current_version and target_version are different - scenario -AB', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
describe('if current_version and target_version are different - scenario -AB', () => { | |
describe('and current and target rule versions are different - scenario -AB', () => { |
describe('returns SOLVABLE conflict if rule is customized', () => { | ||
it('if versions are different types', () => { | ||
const mockVersions: ThreeVersionsOf<RuleDataSource | undefined> = { | ||
base_version: MissingVersion, | ||
current_version: { type: DataSourceType.data_view, data_view_id: '456' }, | ||
target_version: { | ||
type: DataSourceType.index_patterns, | ||
index_patterns: ['one', 'three', 'four'], | ||
}, | ||
}; | ||
|
||
const result = dataSourceDiffAlgorithm(mockVersions, true); | ||
|
||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
has_base_version: false, | ||
base_version: undefined, | ||
merged_version: mockVersions.target_version, | ||
diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, | ||
merge_outcome: ThreeWayMergeOutcome.Target, | ||
conflict: ThreeWayDiffConflict.SOLVABLE, | ||
}) | ||
); | ||
}); | ||
|
||
it('if current version is undefined', () => { | ||
const mockVersions: ThreeVersionsOf<RuleDataSource | undefined> = { | ||
base_version: MissingVersion, | ||
current_version: undefined, | ||
target_version: { | ||
type: DataSourceType.index_patterns, | ||
index_patterns: ['one', 'three', 'four'], | ||
}, | ||
}; | ||
|
||
const result = dataSourceDiffAlgorithm(mockVersions, true); | ||
|
||
expect(result).toEqual( | ||
expect.objectContaining({ | ||
has_base_version: false, | ||
base_version: undefined, | ||
merged_version: mockVersions.target_version, | ||
diff_outcome: ThreeWayDiffOutcome.MissingBaseCanUpdate, | ||
merge_outcome: ThreeWayMergeOutcome.Target, | ||
conflict: ThreeWayDiffConflict.SOLVABLE, | ||
}) | ||
); | ||
}); | ||
}); | ||
}); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Context and test names are reversed here. A general rule of thumb describe
defines a context like when rule is customized
or with conflicts
and it
says what's expected like returns true
or returns a SOLVABLE conflict
.
...etection_engine/prebuilt_rules/logic/diff/calculation/algorithms/rule_type_diff_algorithm.ts
Outdated
Show resolved
Hide resolved
...gins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx
Outdated
Show resolved
Hide resolved
...gins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx
Outdated
Show resolved
Hide resolved
...gins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx
Outdated
Show resolved
Hide resolved
...gins/security_solution/public/detection_engine/rule_creation_ui/pages/rule_editing/index.tsx
Outdated
Show resolved
Hide resolved
💚 Build Succeeded
Metrics [docs]Module Count
Async chunks
History
cc @dplumlee |
Summary
Partially addresses #210358
Adds all callouts and logic to incentivize users to upgrade their rules asap. These include:
This PR also adds related updates to the rule diff algorithms in order to facilitate an easier upgrade experience when rules have missing base versions. These include:
SOLVABLE_CONFLICT
.tags
,references
,new_terms_fields
,threat_index
). We typically also consider multi-line string fields as mergeable but without three versions of the string, we are currently unable to merge the strings together, so we just return target version.index
) and non-mergeable fields and return them asSOLVABLE_CONFLICT
.Screenshots
Callout on Rule details page w/ flyout button

Upgrade flyout now accessible from rule details page

Callout on rule editing page

Dismissible callout on rule management page

Callout in rule upgrade flyout when rule has missing base version

Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.