-
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] Extend upgrade prebuilt rules context with conflict resolution functionality #191721
[Security Solution] Extend upgrade prebuilt rules context with conflict resolution functionality #191721
Conversation
64bb1e5
to
9503044
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) |
9503044
to
3425c13
Compare
rule={rule} | ||
size="l" | ||
id={PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR} | ||
dataTestSubj="updatePrebuiltRulePreview" |
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 need to allow passing dataTestSubj
via props, because we used:
dataTestSubj="installPrebuiltRulePreview"
for installationdataTestSubj="updatePrebuiltRulePreview"
for upgrade
We have a Cypress test that uses these, but it doesn't run because it has issues with tags. I have created a PR to make it run again. We'll need to run these changes through CI once that PR is merged.
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.
Also id={PREBUILT_RULE_UPDATE_FLYOUT_ANCHOR}
is not needed for the installation use case. I'm thinking maybe we could have a generic prop like flyoutProps
that we would spread over? wdyt?
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.
Yes, thanks for noticing. I planned to address data test subject ids in follow up PRs where we add tests. As you can see the current code doesn't cause any failures.
Adding flyoutProps
right away looks as a good option.
3425c13
to
2071dff
Compare
isUpgradingSecurityPackages, | ||
installOneRule, | ||
] | ||
); |
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.
Add a space after this line for clarity?
ruleResolvedConflicts: RuleResolvedConflicts | ||
): DiffableRule { | ||
return { | ||
...convertRuleToDiffable(ruleUpgradeInfo.target_rule), |
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.
I'm not sure if this is WIP, but if we want to get the "final version" of a rule, we should get all diffable fields, and then overwrite all fields that have a merged_version
within diff.fields
.
The logic here implemented is correct, but it will only work when the user manually does a change in the edit component.
I think the return value of this method should look something like:
return {
...convertRuleToDiffable(ruleUpgradeInfo.target_rule),
...getFieldsWithMergedVersions(ruleUpgradeInfo.diff), // loops through diff.fields and retrieves fields with a merged_version
...ruleResolvedConflicts,
} as DiffableRule;
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.
This will make sure to use the target
version as the "initial" diffable rule, then overwrite with any values that were returned with a merged_version
from /upgrade/_review, and finally overwrite any values that have been manually edited by the user.
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.
Thanks. It makes sense. I made proper adjustments in the code.
const fieldNamesWithNonSolvableConflicts = fieldNames.filter( | ||
(fieldName) => | ||
ruleUpgradeInfo.diff.fields[fieldName]?.conflict === ThreeWayDiffConflict.NON_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.
We spoke about this today, but posting here for transparency: this should include the fields with SOLVABLE
conflicts, which should be accepted by the user as well in order to unblock the upgrade of the rule.
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.
Yes. I changed the implementation to match our discussion results.
...ruleUpgradeInfo, | ||
finalRule: calcFinalDiffableRule( | ||
ruleUpgradeInfo, | ||
rulesResolvedConflicts[ruleUpgradeInfo.id] ?? {} |
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.
If understand it correctly, we should use ruleUpgradeInfo.rule_id
here and when calling calcUnresolvedConflicts
below. Otherwise it won't find an item in rulesResolvedConflicts
.
2071dff
to
6663685
Compare
export function usePrebuiltRulesUpgradeState( | ||
ruleUpgradeInfos: RuleUpgradeInfoForReview[] | ||
): UseRulesUpgradeStateResult { | ||
const [rulesResolvedConflicts, setRulesResolvedConflicts] = useState<RulesResolvedConflicts>({}); |
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.
I wonder if we should also let the user revert a conflict back to unresolved. Let's say they set some resolved value and then decide that it's not good and they want to start over from the initial state (merge proposal). In current implementation even if you close and reopen the flyout the state will be preserved. And if we later add persistence in sessionStorage
even page reload won't help.
Should we then think about adding buttons for reverting? @maximpn @jpdjere
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.
Yes. It might be helpful feature. But it's possible to implement this feature on top of the current functionality. I wouldn't address that in the current PR.
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.
Yep, I agree, it's for a separate PR. I'm curious what you folks think in general about reverts - is it needed or not. Because it's something that we haven't discussed when planning the feature.
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'll definitely need a way to "revert" conflict resolutions. Just as an example: a rule update has an ABC scenario conflict for its name
field. The user manually resolves the conflict, but then manually deletes the input value in the edit component. Since name
is required, we should unresolve the conflict and disable the "Update rule" button.
But yes, we can add this complexity incrementally, doesn't need to be part of this PR.
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.
Just realized that my message above refers to unresolving a conflict from the state management point of view (which can be handled using the existing setRulesResolvedConflicts
setter), but what @nikitaindik meant was allowing the user to unaccept a change from the UI/UX perspective.
In the original plan, for each field, we'd have a Edit/Save button that switches back and forth between those two values when clicking on it. When clicking on Save, the change is accepted and conflict resolved, when clicking on Edit, it is un-accepted and conflict un-resolved.
However, this has one limitation that we need to resolved. Copying here what I pasted on Slack yesterday:
There's one thing that I think we need to figure out: when planning out this component we decided to simplify the UI by just having a button that switches back and forth betwen Edit and Save. And by clicking on "Save", that would mark the state as "accepted".
However, since the "SOLVABLE" conflicts appear first as Read-Only components, they are already "saved" from the UI perspective (the Edit button is visible, no the Save button), but not from the state management perspective. It feels like we still need to add a separate button to accept the changes, that is independent from the Edit/Save switch. But I'm afraid this might explode the complexity of the component's state.
What do you guys think? cc @maximpn
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.
Continued the discussion in the Slack channel pasted above.
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.
Thanks for addressing my comments. Now I see the expected finalVersion
with the merged_versions of the fields that have updated. 👍
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.
Thanks for the changes @maximpn! PR LGTM now.
💛 Build succeeded, but was flaky
Failed CI StepsMetrics [docs]Module Count
Async chunks
History
To update your PR or re-run it, just comment with: cc @maximpn |
…Customization FF (#192919) ## Summary With the merge of #191721, new logic was introduce to disable the Upgrade rule button in the Rule Upgrade table for rules which have conflicts in any of their fields. **This change should be hidden behind a FF.** Otherwise the UI upgrade flow might break for any users who might have customized the rule via API and generated conflicts.
…Update Workflow (#193531) **Epic:** #174168 **Addresses:** #171520 ## Summary This PR introduces a new `Update` tab allowing users to resolve rule upgrade conflicts. It's a result of combination of read-only components implemented in #193261 and rule upgrade state implemented in #191721. ## Details The goal of this PR is to provide intermediate integration between rule upgrade state ([PR](#191721)) and components displaying the diff and read-only state ([PR](#193261)). It will facilitate further development of rule field editable components and streamline rule upgrade functionality developing. ## How to test? The functionality is hidden under `prebuiltRulesCustomizationEnabled` feature flag. Add the following to your Kibana config ```yaml xpack.securitySolution.enableExperimental: - prebuiltRulesCustomizationEnabled ``` When the above feature flag enabled the new `Update` tab is displayed instead of the old one. ## Screenshots Suggested components design ![image](https://github.com/user-attachments/assets/b5aaf571-286a-4595-9bd4-fdaf9a423b03) New `Update` tab <img width="1718" alt="image" src="https://github.com/user-attachments/assets/28aa6bb3-f805-4109-a808-d67e58c7c5b8">
…Update Workflow (elastic#193531) **Epic:** elastic#174168 **Addresses:** elastic#171520 ## Summary This PR introduces a new `Update` tab allowing users to resolve rule upgrade conflicts. It's a result of combination of read-only components implemented in elastic#193261 and rule upgrade state implemented in elastic#191721. ## Details The goal of this PR is to provide intermediate integration between rule upgrade state ([PR](elastic#191721)) and components displaying the diff and read-only state ([PR](elastic#193261)). It will facilitate further development of rule field editable components and streamline rule upgrade functionality developing. ## How to test? The functionality is hidden under `prebuiltRulesCustomizationEnabled` feature flag. Add the following to your Kibana config ```yaml xpack.securitySolution.enableExperimental: - prebuiltRulesCustomizationEnabled ``` When the above feature flag enabled the new `Update` tab is displayed instead of the old one. ## Screenshots Suggested components design ![image](https://github.com/user-attachments/assets/b5aaf571-286a-4595-9bd4-fdaf9a423b03) New `Update` tab <img width="1718" alt="image" src="https://github.com/user-attachments/assets/28aa6bb3-f805-4109-a808-d67e58c7c5b8"> (cherry picked from commit 878ba13)
… Rule Update Workflow (#193531) (#194348) # Backport This will backport the following commits from `main` to `8.x`: - [[Security Solution] Integrate state and components for Prebuilt Rule Update Workflow (#193531)](#193531) <!--- Backport version: 9.4.3 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Maxim Palenov","email":"maxim.palenov@elastic.co"},"sourceCommit":{"committedDate":"2024-09-27T21:07:12Z","message":"[Security Solution] Integrate state and components for Prebuilt Rule Update Workflow (#193531)\n\n**Epic:** https://github.com/elastic/kibana/issues/174168\r\n**Addresses:** https://github.com/elastic/kibana/issues/171520\r\n\r\n## Summary\r\n\r\nThis PR introduces a new `Update` tab allowing users to resolve rule upgrade conflicts. It's a result of combination of read-only components implemented in #193261 and rule upgrade state implemented in https://github.com/elastic/kibana/pull/191721.\r\n\r\n## Details\r\n\r\nThe goal of this PR is to provide intermediate integration between rule upgrade state ([PR](#191721)) and components displaying the diff and read-only state ([PR](#193261)). It will facilitate further development of rule field editable components and streamline rule upgrade functionality developing.\r\n\r\n## How to test?\r\n\r\nThe functionality is hidden under `prebuiltRulesCustomizationEnabled` feature flag. Add the following to your Kibana config\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:\r\n - prebuiltRulesCustomizationEnabled\r\n```\r\n\r\nWhen the above feature flag enabled the new `Update` tab is displayed instead of the old one.\r\n\r\n## Screenshots\r\n\r\nSuggested components design \r\n![image](https://github.com/user-attachments/assets/b5aaf571-286a-4595-9bd4-fdaf9a423b03)\r\n\r\nNew `Update` tab\r\n<img width=\"1718\" alt=\"image\" src=\"https://github.com/user-attachments/assets/28aa6bb3-f805-4109-a808-d67e58c7c5b8\">","sha":"878ba134e96245b038a9765148ad48a36bb2aa4b","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Detections and Resp","Team: SecuritySolution","Team:Detection Rule Management","backport:prev-minor"],"title":"[Security Solution] Integrate state and components for Prebuilt Rule Update Workflow","number":193531,"url":"https://github.com/elastic/kibana/pull/193531","mergeCommit":{"message":"[Security Solution] Integrate state and components for Prebuilt Rule Update Workflow (#193531)\n\n**Epic:** https://github.com/elastic/kibana/issues/174168\r\n**Addresses:** https://github.com/elastic/kibana/issues/171520\r\n\r\n## Summary\r\n\r\nThis PR introduces a new `Update` tab allowing users to resolve rule upgrade conflicts. It's a result of combination of read-only components implemented in #193261 and rule upgrade state implemented in https://github.com/elastic/kibana/pull/191721.\r\n\r\n## Details\r\n\r\nThe goal of this PR is to provide intermediate integration between rule upgrade state ([PR](#191721)) and components displaying the diff and read-only state ([PR](#193261)). It will facilitate further development of rule field editable components and streamline rule upgrade functionality developing.\r\n\r\n## How to test?\r\n\r\nThe functionality is hidden under `prebuiltRulesCustomizationEnabled` feature flag. Add the following to your Kibana config\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:\r\n - prebuiltRulesCustomizationEnabled\r\n```\r\n\r\nWhen the above feature flag enabled the new `Update` tab is displayed instead of the old one.\r\n\r\n## Screenshots\r\n\r\nSuggested components design \r\n![image](https://github.com/user-attachments/assets/b5aaf571-286a-4595-9bd4-fdaf9a423b03)\r\n\r\nNew `Update` tab\r\n<img width=\"1718\" alt=\"image\" src=\"https://github.com/user-attachments/assets/28aa6bb3-f805-4109-a808-d67e58c7c5b8\">","sha":"878ba134e96245b038a9765148ad48a36bb2aa4b"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/193531","number":193531,"mergeCommit":{"message":"[Security Solution] Integrate state and components for Prebuilt Rule Update Workflow (#193531)\n\n**Epic:** https://github.com/elastic/kibana/issues/174168\r\n**Addresses:** https://github.com/elastic/kibana/issues/171520\r\n\r\n## Summary\r\n\r\nThis PR introduces a new `Update` tab allowing users to resolve rule upgrade conflicts. It's a result of combination of read-only components implemented in #193261 and rule upgrade state implemented in https://github.com/elastic/kibana/pull/191721.\r\n\r\n## Details\r\n\r\nThe goal of this PR is to provide intermediate integration between rule upgrade state ([PR](#191721)) and components displaying the diff and read-only state ([PR](#193261)). It will facilitate further development of rule field editable components and streamline rule upgrade functionality developing.\r\n\r\n## How to test?\r\n\r\nThe functionality is hidden under `prebuiltRulesCustomizationEnabled` feature flag. Add the following to your Kibana config\r\n\r\n```yaml\r\nxpack.securitySolution.enableExperimental:\r\n - prebuiltRulesCustomizationEnabled\r\n```\r\n\r\nWhen the above feature flag enabled the new `Update` tab is displayed instead of the old one.\r\n\r\n## Screenshots\r\n\r\nSuggested components design \r\n![image](https://github.com/user-attachments/assets/b5aaf571-286a-4595-9bd4-fdaf9a423b03)\r\n\r\nNew `Update` tab\r\n<img width=\"1718\" alt=\"image\" src=\"https://github.com/user-attachments/assets/28aa6bb3-f805-4109-a808-d67e58c7c5b8\">","sha":"878ba134e96245b038a9765148ad48a36bb2aa4b"}}]}] BACKPORT--> Co-authored-by: Maxim Palenov <maxim.palenov@elastic.co>
Addresses: #171520
Summary
This PR implements necessary
UpgradePrebuiltRulesTableContext
changes to provide uses a way to resolve conflicts manually by providing field's resolved value.Details
During prebuilt rules upgrading users may encounter solvable and non-solvable conflicts between customized and target rule versions. Three-Way-Diff field component allow to specify a desired resolve value user expects to be in the rule after upgrading. It's also possible to customize rules during the upgrading process.
Current functionality is informational only without an ability to customize prebuilt rules. As the core part of that process it's required to manage the upgrading state and provide necessary data for downstream components rendering field diffs and accepting user input.
This PR extends
UpgradePrebuiltRulesTableContext
with rule upgrade state and provides it toThreeWayDiffTab
stub component. It's planned to add implementation toThreeWayDiffTab
in follow up PRs.On top of that
UpgradePrebuiltRulesTableContext
andAddPrebuiltRulesTableContext
were symmetrically refactored from architecture point of view to improve encapsulation by separation of concerns which leads to slight complexity reduction.Feature flag
prebuiltRulesCustomizationEnabled
ThreeWayDiffTab
is hidden under a feature flagprebuiltRulesCustomizationEnabled
. It accepts afinalDiffableRule
which represents rule fields the user expects to see in the upgraded rule.finalDiffableRule
is a combination of field resolved values and target rule fields where resolved values have precedence.