[Security Solution][Detection Engine] Exceptions auto-populate not working for numeric filed values (#164713)

## Summary

- Fixes https://github.com/elastic/kibana/issues/163924

As we utilize either the [
Match](https://github.com/WafaaNasr/kibana/blob/main/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx#L384)
or
[Match_Any](https://github.com/WafaaNasr/kibana/blob/main/x-pack/plugins/lists/public/exceptions/components/builder/entry_renderer.tsx#L402),
operator, the anticipated values should be limited to either strings or
arrays containing strings.
This commit is contained in:
Wafaa Nasr 2023-08-25 13:42:53 +02:00 committed by GitHub
parent c7dd76dd7d
commit e8127e275f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 111 additions and 7 deletions

View file

@ -1467,6 +1467,16 @@ describe('Exception helpers', () => {
capabilities: endpointCapabilties,
},
_id: 'b9edb05a090729be2077b99304542d6844973843dec43177ac618f383df44a6d',
destination: {
port: 443,
},
source: {
ports: [1, 2, 4],
},
flow: {
final: false,
skip: true,
},
};
const expectedHighlightedFields = [
{
@ -1645,6 +1655,68 @@ describe('Exception helpers', () => {
});
expect(entries).toEqual(expectedExceptionEntries);
});
it('should build exception entries with "match" operator and ensure that integer value is converted to a string', () => {
const entries = buildExceptionEntriesFromAlertFields({
highlightedFields: [
...expectedHighlightedFields,
{
id: 'destination.port',
},
],
alertData,
});
expect(alertData).toEqual(
expect.objectContaining({
destination: {
port: 443,
},
})
);
expect(entries).toEqual([
...expectedExceptionEntries,
{
field: 'destination.port',
operator: 'included',
type: 'match',
value: '443',
},
]);
});
it('should build exception entries with "match" operator and ensure that boolean value is converted to a string', () => {
const entries = buildExceptionEntriesFromAlertFields({
highlightedFields: [
...expectedHighlightedFields,
{
id: 'flow.final',
},
{ id: 'flow.skip' },
],
alertData,
});
expect(alertData).toEqual(
expect.objectContaining({
flow: {
final: false,
skip: true,
},
})
);
expect(entries).toEqual([
...expectedExceptionEntries,
{
field: 'flow.final',
operator: 'included',
type: 'match',
value: 'false',
},
{
field: 'flow.skip',
operator: 'included',
type: 'match',
value: 'true',
},
]);
});
it('should build the exception entries with "match_any" in case the field key has multiple values', () => {
const entries = buildExceptionEntriesFromAlertFields({
highlightedFields: [
@ -1657,6 +1729,26 @@ describe('Exception helpers', () => {
});
expect(entries).toEqual([...expectedExceptionEntries, entriesWithMatchAny]);
});
it('should build the exception entries with "match_any" in case the field key has multiple values and ensure that the array value is converted to a string', () => {
const entries = buildExceptionEntriesFromAlertFields({
highlightedFields: [
...expectedHighlightedFields,
{
id: 'source.ports',
},
],
alertData,
});
expect(entries).toEqual([
...expectedExceptionEntries,
{
field: 'source.ports',
operator,
type: ListOperatorTypeEnum.MATCH_ANY,
value: ['1', '2', '4'],
},
]);
});
});
describe('filterHighlightedFields', () => {

View file

@ -874,6 +874,9 @@ export const buildRuleExceptionWithConditions = ({
Generate exception conditions based on the highlighted fields of the alert that
have corresponding values in the alert data.
For the initial implementation the nested conditions are not considered
Converting a singular value to a string or an array of strings
is necessary because the "Match" or "Match any" operators
are designed to operate with string value(s).
*/
export const buildExceptionEntriesFromAlertFields = ({
highlightedFields,
@ -884,18 +887,24 @@ export const buildExceptionEntriesFromAlertFields = ({
}): EntriesArray => {
return Object.values(highlightedFields).reduce((acc: EntriesArray, field) => {
const fieldKey = field.id;
const fieldValue = get(alertData, fieldKey) || get(alertData, getKibanaAlertIdField(fieldKey));
const fieldValue = get(alertData, fieldKey) ?? get(alertData, getKibanaAlertIdField(fieldKey));
if (fieldValue) {
if (fieldValue !== null && fieldValue !== undefined) {
const listOperatorType = Array.isArray(fieldValue)
? ListOperatorTypeEnum.MATCH_ANY
: ListOperatorTypeEnum.MATCH;
const fieldValueAsString = Array.isArray(fieldValue)
? fieldValue.map(String)
: fieldValue.toString();
acc.push({
field: fieldKey,
operator: ListOperatorEnum.INCLUDED,
type: Array.isArray(fieldValue)
? ListOperatorTypeEnum.MATCH_ANY
: ListOperatorTypeEnum.MATCH,
value: fieldValue,
type: listOperatorType,
value: fieldValueAsString,
});
}
return acc;
}, []);
};
@ -917,7 +926,10 @@ export const getPrepopulatedRuleExceptionWithHighlightFields = ({
const highlightedFields = getAlertHighlightedFields(alertData, ruleCustomHighlightedFields);
if (!highlightedFields.length) return null;
const exceptionEntries = buildExceptionEntriesFromAlertFields({ highlightedFields, alertData });
const exceptionEntries = buildExceptionEntriesFromAlertFields({
highlightedFields,
alertData,
});
if (!exceptionEntries.length) return null;
return buildRuleExceptionWithConditions({