[8.x] [Security Solution] [Attack discovery] Use common replacements function (#193645) (#194198)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Security Solution] [Attack discovery] Use common replacements
function (#193645)](https://github.com/elastic/kibana/pull/193645)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Andrew
Macri","email":"andrew.macri@elastic.co"},"sourceCommit":{"committedDate":"2024-09-26T17:08:32Z","message":"[Security
Solution] [Attack discovery] Use common replacements function
(#193645)\n\n### [Security Solution] [Attack discovery] Use common
replacements function\r\n\r\nThis PR is a follow-up to
<https://github.com/elastic/kibana/pull/193428>, to make use of the
common function for replacing anonymized values with original
values","sha":"30831e61568d4cd58aec2493767180e05ea3ec28","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:
SecuritySolution","Team:Security Generative
AI","v8.16.0","backport:version","v8.15.3"],"title":"[Security Solution]
[Attack discovery] Use common replacements
function","number":193645,"url":"https://github.com/elastic/kibana/pull/193645","mergeCommit":{"message":"[Security
Solution] [Attack discovery] Use common replacements function
(#193645)\n\n### [Security Solution] [Attack discovery] Use common
replacements function\r\n\r\nThis PR is a follow-up to
<https://github.com/elastic/kibana/pull/193428>, to make use of the
common function for replacing anonymized values with original
values","sha":"30831e61568d4cd58aec2493767180e05ea3ec28"}},"sourceBranch":"main","suggestedTargetBranches":["8.x","8.15"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/193645","number":193645,"mergeCommit":{"message":"[Security
Solution] [Attack discovery] Use common replacements function
(#193645)\n\n### [Security Solution] [Attack discovery] Use common
replacements function\r\n\r\nThis PR is a follow-up to
<https://github.com/elastic/kibana/pull/193428>, to make use of the
common function for replacing anonymized values with original
values","sha":"30831e61568d4cd58aec2493767180e05ea3ec28"}},{"branch":"8.x","label":"v8.16.0","branchLabelMappingKey":"^v8.16.0$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.15","label":"v8.15.3","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Andrew Macri <andrew.macri@elastic.co>
This commit is contained in:
Kibana Machine 2024-09-27 04:37:56 +10:00 committed by GitHub
parent 07e52509b1
commit 3094a7e8b7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 58 additions and 17 deletions

View file

@ -5,7 +5,13 @@
* 2.0.
*/
import { isAllowed, isAnonymized, isDenied, getIsDataAnonymizable } from '.';
import {
isAllowed,
isAnonymized,
isDenied,
getIsDataAnonymizable,
replaceAnonymizedValuesWithOriginalValues,
} from '.';
const anonymizationFields = [
{ id: 'fieldName1', field: 'fieldName1', allowed: true, anonymized: false },
@ -91,4 +97,41 @@ describe('helpers', () => {
expect(isAnonymized({ anonymizationFields: [], field: 'user.name' })).toBe(false);
});
});
describe('replaceAnonymizedValuesWithOriginalValues', () => {
const replacements = {
'3541b730-1dce-4937-b63f-0d618ea1cc5f': 'not-an-administrator',
'b222e892-431e-4e4f-9295-2ba92ef9d12d': 'domain-controller',
};
it('replaces anonymized values with original values', () => {
const messageContent =
'User {{ user.name 3541b730-1dce-4937-b63f-0d618ea1cc5f }} added a member to the Administrators group on host {{ host.name b222e892-431e-4e4f-9295-2ba92ef9d12d }}';
const result = replaceAnonymizedValuesWithOriginalValues({ messageContent, replacements });
expect(result).toEqual(
'User {{ user.name not-an-administrator }} added a member to the Administrators group on host {{ host.name domain-controller }}'
);
});
it('returns the original messageContent if no replacements are found', () => {
const messageContent = 'There are no replacements applicable to this message';
const result = replaceAnonymizedValuesWithOriginalValues({ messageContent, replacements });
expect(result).toEqual(messageContent);
});
it('replaces multiple occurrences of the same replacement key', () => {
const messageContent =
'User {{ user.name 3541b730-1dce-4937-b63f-0d618ea1cc5f }} added a member to the Administrators group on host {{ host.name b222e892-431e-4e4f-9295-2ba92ef9d12d }}, which is unusual because {{ user.name 3541b730-1dce-4937-b63f-0d618ea1cc5f }} is not a member of the Administrators group.';
const result = replaceAnonymizedValuesWithOriginalValues({ messageContent, replacements });
expect(result).toEqual(
'User {{ user.name not-an-administrator }} added a member to the Administrators group on host {{ host.name domain-controller }}, which is unusual because {{ user.name not-an-administrator }} is not a member of the Administrators group.'
);
});
});
});

View file

@ -42,12 +42,11 @@ export const replaceAnonymizedValuesWithOriginalValues = ({
messageContent: string;
replacements: Replacements;
}): string =>
replacements != null
? Object.keys(replacements).reduce((acc, key) => {
const value = replacements[key];
return acc.replaceAll(key, value);
}, messageContent)
: messageContent;
Object.keys(replacements).reduce((acc, key) => {
const value = replacements[key];
return acc.replaceAll(key, value);
}, messageContent);
export const replaceOriginalValuesWithUuidValues = ({
messageContent,

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { replaceAnonymizedValuesWithOriginalValues } from '@kbn/elastic-assistant-common';
import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common';
import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer, EuiTitle, useEuiTheme } from '@elastic/eui';
import { css } from '@emotion/react';
@ -34,21 +35,19 @@ const AttackDiscoveryTabComponent: React.FC<Props> = ({
const summaryMarkdownWithReplacements = useMemo(
() =>
Object.entries<string>(replacements ?? {}).reduce((acc, [key, value]) => {
const regex = new RegExp(key, 'g');
return acc.replace(regex, value);
}, summaryMarkdown),
replaceAnonymizedValuesWithOriginalValues({
messageContent: summaryMarkdown,
replacements: replacements ?? {},
}),
[replacements, summaryMarkdown]
);
const detailsMarkdownWithReplacements = useMemo(
() =>
Object.entries<string>(replacements ?? {}).reduce((acc, [key, value]) => {
const regex = new RegExp(key, 'g');
return acc.replace(regex, value);
}, detailsMarkdown),
replaceAnonymizedValuesWithOriginalValues({
messageContent: detailsMarkdown,
replacements: replacements ?? {},
}),
[detailsMarkdown, replacements]
);