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

[Security Solution] Handle negative lookback in rule upgrade flyout #204317

Merged
Merged
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ x-pack/solutions/security/packages/kbn-securitysolution-list-hooks @elastic/secu
x-pack/solutions/security/packages/kbn-securitysolution-list-utils @elastic/security-detection-engine
x-pack/solutions/security/packages/kbn-securitysolution-lists-common @elastic/security-detection-engine
x-pack/solutions/security/packages/kbn-securitysolution-t-grid @elastic/security-detection-engine
x-pack/solutions/security/packages/kbn-securitysolution-utils @elastic/security-detection-engine
x-pack/solutions/security/packages/kbn-securitysolution-utils @elastic/security-detection-engine @elastic/security-detection-rule-management
x-pack/solutions/security/packages/navigation @elastic/security-threat-hunting-explore
x-pack/solutions/security/packages/side_nav @elastic/security-threat-hunting-explore
x-pack/solutions/security/packages/storybook/config @elastic/security-threat-hunting-explore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36637,7 +36637,6 @@
"xpack.securitySolution.detectionEngine.ruleDetails.enableRuleLabel": "Activer",
"xpack.securitySolution.detectionEngine.ruleDetails.endpointExceptionsTab": "Exceptions de point de terminaison",
"xpack.securitySolution.detectionEngine.ruleDetails.falsePositivesFieldLabel": "Exemples de faux positifs",
"xpack.securitySolution.detectionEngine.ruleDetails.fromFieldLabel": "Temps de récupération supplémentaire",
"xpack.securitySolution.detectionEngine.ruleDetails.historyWindowSizeFieldLabel": "Taille de la fenêtre d’historique",
"xpack.securitySolution.detectionEngine.ruleDetails.indexFieldLabel": "Modèles d'indexation",
"xpack.securitySolution.detectionEngine.ruleDetails.installAndEnableButtonLabel": "Installer et activer",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36496,7 +36496,6 @@
"xpack.securitySolution.detectionEngine.ruleDetails.enableRuleLabel": "有効にする",
"xpack.securitySolution.detectionEngine.ruleDetails.endpointExceptionsTab": "エンドポイント例外",
"xpack.securitySolution.detectionEngine.ruleDetails.falsePositivesFieldLabel": "誤検出の例",
"xpack.securitySolution.detectionEngine.ruleDetails.fromFieldLabel": "追加のルックバック時間",
"xpack.securitySolution.detectionEngine.ruleDetails.historyWindowSizeFieldLabel": "履歴ウィンドウサイズ",
"xpack.securitySolution.detectionEngine.ruleDetails.indexFieldLabel": "インデックスパターン",
"xpack.securitySolution.detectionEngine.ruleDetails.installAndEnableButtonLabel": "インストールして有効化",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35954,7 +35954,6 @@
"xpack.securitySolution.detectionEngine.ruleDetails.enableRuleLabel": "启用",
"xpack.securitySolution.detectionEngine.ruleDetails.endpointExceptionsTab": "终端例外",
"xpack.securitySolution.detectionEngine.ruleDetails.falsePositivesFieldLabel": "误报示例",
"xpack.securitySolution.detectionEngine.ruleDetails.fromFieldLabel": "更多回查时间",
"xpack.securitySolution.detectionEngine.ruleDetails.historyWindowSizeFieldLabel": "历史记录窗口大小",
"xpack.securitySolution.detectionEngine.ruleDetails.indexFieldLabel": "索引模式",
"xpack.securitySolution.detectionEngine.ruleDetails.installAndEnableButtonLabel": "安装并启用",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export * from './src/date_math';
banderror marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
{
"type": "shared-common",
"id": "@kbn/securitysolution-utils",
"owner": [
"@elastic/security-detection-engine"
],
"owner": ["@elastic/security-detection-engine", "@elastic/security-detection-rule-management"],
"group": "security",
"visibility": "private"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { calcDateMathDiff } from './calc_date_math_diff';

describe('calcDateMathDiff', () => {
it.each([
['now-62s', 'now-1m', 2000],
['now-122s', 'now-1m', 62000],
['now-660s', 'now-5m', 360000],
['now-6600s', 'now-5m', 6300000],
['now-7500s', 'now-5m', 7200000],
['now-1m', 'now-62s', -2000],
['now-1m', 'now-122s', -62000],
['now-5m', 'now-660s', -360000],
['now-5m', 'now-6600s', -6300000],
['now-5m', 'now-7500s', -7200000],
['now-1s', 'now-1s', 0],
['now-1m', 'now-1m', 0],
['now-1h', 'now-1h', 0],
['now-1d', 'now-1d', 0],
])('calculates milliseconds diff between "%s" and "%s"', (start, end, expected) => {
const result = calcDateMathDiff(start, end);

expect(result).toEqual(expected);
});

test('returns "undefined" when start is invalid date math', () => {
const result = calcDateMathDiff('invalid', 'now-5m');

expect(result).toBeUndefined();
});

test('returns "undefined" when end is invalid date math', () => {
const result = calcDateMathDiff('now-300s', 'invalid');

expect(result).toBeUndefined();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import dateMath from '@kbn/datemath';

/**
* Calculates difference between date math expressions in milliseconds.
*/
export function calcDateMathDiff(start: string, end: string): number | undefined {
const now = new Date();
const startMoment = dateMath.parse(start, { forceNow: now });
const endMoment = dateMath.parse(end, { forceNow: now });

if (!startMoment || !endMoment) {
return undefined;
}

const result = endMoment.diff(startMoment, 'ms');

return !isNaN(result) ? result : undefined;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

export * from './calc_date_math_diff';
export * from './normalize_date_math';
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { normalizeDateMath } from './normalize_date_math';

describe('normalizeDateMath', () => {
it.each([
['now-60s', 'now-1m'],
['now-60m', 'now-1h'],
['now-24h', 'now-1d'],
['now+60s', 'now+1m'],
['now+60m', 'now+1h'],
['now+24h', 'now+1d'],
])('normalizes %s', (sourceDateMath, normalizedDateMath) => {
const result = normalizeDateMath(sourceDateMath);

expect(result).toBe(normalizedDateMath);
});

it.each([['now'], ['now-invalid'], ['invalid']])('returns %s non-normalized', (dateMath) => {
const result = normalizeDateMath(dateMath);

expect(result).toBe(dateMath);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { TimeDuration } from '../time_duration/time_duration';
import { calcDateMathDiff } from './calc_date_math_diff';

/**
* Normalizes date math
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we have the tests to demonstrate functionality, but perhaps we could expound here as well:

Suggested change
* Normalizes date math
* Normalizes date math strings by reducing time units, when possible
* Example: "now-60s" -> "now-1h"
* Example: "now-72s" -> "now-72s"

*/
export function normalizeDateMath(input: string): string {
try {
const ms = calcDateMathDiff('now', input);

if (ms === undefined || (ms > -1000 && ms < 1000)) {
return input;
}

if (ms === 0) {
return 'now';
}

const offset = TimeDuration.fromMilliseconds(ms);

return offset.value < 0 ? `now${offset}` : `now+${offset}`;
} catch {
return input;
}
}
Loading