Skip to content

Commit

Permalink
[8.x] [Security Solution] Display unavailable ML jobs (#205483) (#205601
Browse files Browse the repository at this point in the history
)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Security Solution] Display unavailable ML jobs
(#205483)](#205483)

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

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

<!--BACKPORT [{"author":{"name":"Nikita
Indik","email":"[email protected]"},"sourceCommit":{"committedDate":"2025-01-06T12:33:10Z","message":"[Security
Solution] Display unavailable ML jobs (#205483)\n\n**Resolves:
https://github.com/elastic/kibana/issues/202700**\n\n## Summary\nThis PR
resolves an issue where an ML job referenced by a rule does not\nappear
in the Rule Details, Upgrade flyout, or Rule Editing pages if the\njob
is missing or not yet created.\n\nFor example, if you had an ML rule
with a single selected job and this\njob was not available, you would
see a blank space instead of job name.\n\n## Screenshots\n**Rule
Details: Before**\n<img width=\"578\" alt=\"Scherm­afbeelding 2025-01-03
om 13 20
32\"\nsrc=\"https://github.com/user-attachments/assets/e8bc073f-0420-4888-8dd9-b4dc70fd0682\"\n/>\n\n**Rule
Details: After**\n<img width=\"578\" alt=\"Scherm­afbeelding 2025-01-03
om 13 20
05\"\nsrc=\"https://github.com/user-attachments/assets/bd4d0f91-8adf-45c5-8d31-b42ac483027b\"\n/>\n\n**Rule
Edit: Before**\n<img width=\"427\" alt=\"Scherm­afbeelding 2025-01-03 om
13 21
21\"\nsrc=\"https://github.com/user-attachments/assets/bffcb871-8cfc-4f50-8d19-c14b122c0be4\"\n/>\n\n**Rule
Edit: After**\n<img width=\"427\" alt=\"Scherm­afbeelding 2025-01-03 om
13 21
09\"\nsrc=\"https://github.com/user-attachments/assets/be8f60b9-17a6-48d2-978c-cfa63c426a08\"\n/>\n\n**Upgrade
flyout: Before**\n<img width=\"1066\" alt=\"Scherm­afbeelding 2025-01-03
om 13 22
30\"\nsrc=\"https://github.com/user-attachments/assets/553ff837-95cf-4670-91f1-dffb169ec505\"\n/>\n\n**Upgrade
flyout: After**\n<img width=\"1066\" alt=\"Scherm­afbeelding 2025-01-03
om 13 21
55\"\nsrc=\"https://github.com/user-attachments/assets/150cfb82-bc69-4aeb-a20a-03f54c7edc70\"\n/>\n\n##
Testing\nYou can test by removing an ML job referenced by a rule
in\n`http://localhost:<port>/kbn/app/ml/jobs`.","sha":"e04b20018a441e679848e114df68ba688976c83c","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.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","Feature:Prebuilt Detection Rules","Feature:Rule
Creation","Feature:Rule Details","Feature:Rule
Edit","backport:version","v8.18.0"],"title":"[Security Solution] Display
unavailable ML
jobs","number":205483,"url":"https://github.com/elastic/kibana/pull/205483","mergeCommit":{"message":"[Security
Solution] Display unavailable ML jobs (#205483)\n\n**Resolves:
https://github.com/elastic/kibana/issues/202700**\n\n## Summary\nThis PR
resolves an issue where an ML job referenced by a rule does not\nappear
in the Rule Details, Upgrade flyout, or Rule Editing pages if the\njob
is missing or not yet created.\n\nFor example, if you had an ML rule
with a single selected job and this\njob was not available, you would
see a blank space instead of job name.\n\n## Screenshots\n**Rule
Details: Before**\n<img width=\"578\" alt=\"Scherm­afbeelding 2025-01-03
om 13 20
32\"\nsrc=\"https://github.com/user-attachments/assets/e8bc073f-0420-4888-8dd9-b4dc70fd0682\"\n/>\n\n**Rule
Details: After**\n<img width=\"578\" alt=\"Scherm­afbeelding 2025-01-03
om 13 20
05\"\nsrc=\"https://github.com/user-attachments/assets/bd4d0f91-8adf-45c5-8d31-b42ac483027b\"\n/>\n\n**Rule
Edit: Before**\n<img width=\"427\" alt=\"Scherm­afbeelding 2025-01-03 om
13 21
21\"\nsrc=\"https://github.com/user-attachments/assets/bffcb871-8cfc-4f50-8d19-c14b122c0be4\"\n/>\n\n**Rule
Edit: After**\n<img width=\"427\" alt=\"Scherm­afbeelding 2025-01-03 om
13 21
09\"\nsrc=\"https://github.com/user-attachments/assets/be8f60b9-17a6-48d2-978c-cfa63c426a08\"\n/>\n\n**Upgrade
flyout: Before**\n<img width=\"1066\" alt=\"Scherm­afbeelding 2025-01-03
om 13 22
30\"\nsrc=\"https://github.com/user-attachments/assets/553ff837-95cf-4670-91f1-dffb169ec505\"\n/>\n\n**Upgrade
flyout: After**\n<img width=\"1066\" alt=\"Scherm­afbeelding 2025-01-03
om 13 21
55\"\nsrc=\"https://github.com/user-attachments/assets/150cfb82-bc69-4aeb-a20a-03f54c7edc70\"\n/>\n\n##
Testing\nYou can test by removing an ML job referenced by a rule
in\n`http://localhost:<port>/kbn/app/ml/jobs`.","sha":"e04b20018a441e679848e114df68ba688976c83c"}},"sourceBranch":"main","suggestedTargetBranches":["8.x"],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/205483","number":205483,"mergeCommit":{"message":"[Security
Solution] Display unavailable ML jobs (#205483)\n\n**Resolves:
https://github.com/elastic/kibana/issues/202700**\n\n## Summary\nThis PR
resolves an issue where an ML job referenced by a rule does not\nappear
in the Rule Details, Upgrade flyout, or Rule Editing pages if the\njob
is missing or not yet created.\n\nFor example, if you had an ML rule
with a single selected job and this\njob was not available, you would
see a blank space instead of job name.\n\n## Screenshots\n**Rule
Details: Before**\n<img width=\"578\" alt=\"Scherm­afbeelding 2025-01-03
om 13 20
32\"\nsrc=\"https://github.com/user-attachments/assets/e8bc073f-0420-4888-8dd9-b4dc70fd0682\"\n/>\n\n**Rule
Details: After**\n<img width=\"578\" alt=\"Scherm­afbeelding 2025-01-03
om 13 20
05\"\nsrc=\"https://github.com/user-attachments/assets/bd4d0f91-8adf-45c5-8d31-b42ac483027b\"\n/>\n\n**Rule
Edit: Before**\n<img width=\"427\" alt=\"Scherm­afbeelding 2025-01-03 om
13 21
21\"\nsrc=\"https://github.com/user-attachments/assets/bffcb871-8cfc-4f50-8d19-c14b122c0be4\"\n/>\n\n**Rule
Edit: After**\n<img width=\"427\" alt=\"Scherm­afbeelding 2025-01-03 om
13 21
09\"\nsrc=\"https://github.com/user-attachments/assets/be8f60b9-17a6-48d2-978c-cfa63c426a08\"\n/>\n\n**Upgrade
flyout: Before**\n<img width=\"1066\" alt=\"Scherm­afbeelding 2025-01-03
om 13 22
30\"\nsrc=\"https://github.com/user-attachments/assets/553ff837-95cf-4670-91f1-dffb169ec505\"\n/>\n\n**Upgrade
flyout: After**\n<img width=\"1066\" alt=\"Scherm­afbeelding 2025-01-03
om 13 21
55\"\nsrc=\"https://github.com/user-attachments/assets/150cfb82-bc69-4aeb-a20a-03f54c7edc70\"\n/>\n\n##
Testing\nYou can test by removing an ML job referenced by a rule
in\n`http://localhost:<port>/kbn/app/ml/jobs`.","sha":"e04b20018a441e679848e114df68ba688976c83c"}},{"branch":"8.x","label":"v8.18.0","branchLabelMappingKey":"^v8.18.0$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Nikita Indik <[email protected]>
  • Loading branch information
kibanamachine and nikitaindik authored Jan 6, 2025
1 parent 8f66e21 commit b44cff1
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 28 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,6 @@
"avcBanner.body": "Elastic Security passe avec brio le test de protection contre les malwares réalisé par AV-Comparatives",
"avcBanner.readTheBlog.link": "Lire le blog",
"avcBanner.title": "Protection à 100 % sans aucun faux positif.",
"bfetch.advancedSettings.disableBfetchCompressionDeprecation": "Ce paramètre est déclassé et sera supprimé dans la version 9.0 de Kibana.",
"bfetch.advancedSettings.disableBfetchDeprecation": "Ce paramètre est déclassé et sera supprimé dans la version 9.0 de Kibana.",
"bfetch.disableBfetch": "Désactiver la mise en lots de requêtes",
"bfetch.disableBfetchCompression": "Désactiver la compression par lots",
"bfetch.disableBfetchCompressionDesc": "Vous pouvez désactiver la compression par lots. Cela permet de déboguer des requêtes individuelles, mais augmente la taille des réponses.",
"bfetch.disableBfetchDesc": "Désactive la mise en lot des requêtes. Cette option augmente le nombre de requêtes HTTP depuis Kibana, mais permet de les déboguer individuellement.",
"bfetchError.networkError": "Vérifiez votre connexion réseau et réessayez.",
"bfetchError.networkErrorWithStatus": "Vérifiez votre connexion réseau et réessayez. Code {code}",
"cases.components.status.closed": "Fermé",
"cases.components.status.inProgress": "En cours",
"cases.components.status.open": "Ouvrir",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,6 @@
"avcBanner.body": "AV-Comparativesのマルウェア保護テストで高い評価を受けたElastic Security",
"avcBanner.readTheBlog.link": "ブログを読む",
"avcBanner.title": "誤検知がゼロの100%保護。",
"bfetch.advancedSettings.disableBfetchCompressionDeprecation": "この設定はサポートが終了し、Kibana 9.0では削除されます。",
"bfetch.advancedSettings.disableBfetchDeprecation": "この設定はサポートが終了し、Kibana 9.0では削除されます。",
"bfetch.disableBfetch": "リクエストバッチを無効にする",
"bfetch.disableBfetchCompression": "バッチ圧縮を無効にする",
"bfetch.disableBfetchCompressionDesc": "バッチ圧縮を無効にします。個別の要求をデバッグできますが、応答サイズが大きくなります。",
"bfetch.disableBfetchDesc": "リクエストバッチを無効にします。これにより、KibanaからのHTTPリクエスト数は減りますが、個別にリクエストをデバッグできます。",
"bfetchError.networkError": "ネットワーク接続を確認して再試行してください。",
"bfetchError.networkErrorWithStatus": "ネットワーク接続を確認して再試行してください。コード{code}",
"cases.components.status.closed": "終了",
"cases.components.status.inProgress": "進行中",
"cases.components.status.open": "オープン",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,14 +198,6 @@
"avcBanner.body": "在 AV-Comparatives 进行的恶意软件防护测试中,Elastic Security 表现突出",
"avcBanner.readTheBlog.link": "阅读博客",
"avcBanner.title": "提供全面保护,误报率为零。",
"bfetch.advancedSettings.disableBfetchCompressionDeprecation": "此设置已过时,将在 Kibana 9.0 中移除。",
"bfetch.advancedSettings.disableBfetchDeprecation": "此设置已过时,将在 Kibana 9.0 中移除。",
"bfetch.disableBfetch": "禁用请求批处理",
"bfetch.disableBfetchCompression": "禁用批量压缩",
"bfetch.disableBfetchCompressionDesc": "禁用批量压缩。这允许您对单个请求进行故障排查,但会增加响应大小。",
"bfetch.disableBfetchDesc": "禁用请求批处理。这会增加来自 Kibana 的 HTTP 请求数,但允许对单个请求进行故障排查。",
"bfetchError.networkError": "检查您的网络连接,然后重试。",
"bfetchError.networkErrorWithStatus": "检查您的网络连接,然后重试。代码 {code}",
"cases.components.status.closed": "已关闭",
"cases.components.status.inProgress": "进行中",
"cases.components.status.open": "打开",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('MlJobSelect', () => {

it('renders correctly', () => {
const Component = () => {
const field = useFormFieldMock<string[]>();
const field = useFormFieldMock<string[]>({ value: [] });

return <MlJobSelect field={field} loading={false} jobs={[]} />;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,21 @@ export const MlJobSelect: React.FC<MlJobSelectProps> = ({
label: `${job.customSettings?.security_app_display_name} ${job.id}`,
}));

// If rule's ML job is no longer available or has not yet become available, we still want it to appear in the dropdown.
selectedJobIds.forEach((selectedJobId) => {
const isSelectedJobAvailable = jobOptions.some((job) => job.value.id === selectedJobId);
if (!isSelectedJobAvailable) {
jobOptions.push({
value: {
id: selectedJobId,
description: '',
name: selectedJobId,
},
label: selectedJobId,
});
}
});

const selectedJobOptions = jobOptions
.filter((option) => selectedJobIds.includes(option.value.id))
// 'label' defines what is rendered inside the selected ComboBoxPill
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { FC, ReactNode } from 'react';
import React, { memo } from 'react';
import styled from 'styled-components';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { euiThemeVars } from '@kbn/ui-theme';

import type { MlSummaryJob } from '@kbn/ml-plugin/public';
import * as i18n from './translations';
Expand All @@ -21,6 +22,7 @@ import { MlJobStatusBadge } from '../ml_job_status_badge';

const Wrapper = styled.div`
overflow: hidden;
margin-bottom: ${euiThemeVars.euiSizeS};
`;

const MlJobItemComponent: FC<{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import {
EuiFlexItem,
EuiFlexGroup,
EuiLoadingSpinner,
EuiButtonIcon,
EuiPopover,
} from '@elastic/eui';
import type { EuiDescriptionListProps } from '@elastic/eui';
import type {
Expand All @@ -24,6 +26,7 @@ import type { Filter } from '@kbn/es-query';
import type { SavedQuery } from '@kbn/data-plugin/public';
import { mapAndFlattenFilters } from '@kbn/data-plugin/public';
import { FilterItems } from '@kbn/unified-search-plugin/public';
import useToggle from 'react-use/lib/useToggle';
import { isDataView } from '../../../../common/components/query_bar';
import type {
AlertSuppressionMissingFieldsStrategy,
Expand Down Expand Up @@ -237,19 +240,28 @@ interface MachineLearningJobListProps {
}

export const MachineLearningJobList = ({ jobIds, isInteractive }: MachineLearningJobListProps) => {
const { jobs } = useSecurityJobs();
const { jobs: availableJobs } = useSecurityJobs();

if (!jobIds) {
return null;
}

const jobIdsArray = Array.isArray(jobIds) ? jobIds : [jobIds];

const unavailableJobIds = jobIdsArray.filter(
(jobId) => !availableJobs.some((job) => job.id === jobId)
);

if (isInteractive) {
return <MlJobsDescription jobIds={jobIdsArray} />;
return (
<>
<MlJobsDescription jobIds={jobIdsArray} />
<UnavailableMlJobs unavailableJobIds={unavailableJobIds} />
</>
);
}

const relevantJobs = jobs.filter((job) => jobIdsArray.includes(job.id));
const relevantJobs = availableJobs.filter((job) => jobIdsArray.includes(job.id));

return (
<>
Expand All @@ -260,10 +272,48 @@ export const MachineLearningJobList = ({ jobIds, isInteractive }: MachineLearnin
jobName={job.customSettings?.security_app_display_name}
/>
))}
<UnavailableMlJobs unavailableJobIds={unavailableJobIds} />
</>
);
};

interface UnavailableMlJobsProps {
unavailableJobIds: string[];
}

const UnavailableMlJobs = ({ unavailableJobIds }: UnavailableMlJobsProps) => {
return unavailableJobIds.map((jobId) => (
<div key={jobId}>
<UnavailableMlJobLink jobId={jobId} />
</div>
));
};

interface UnavailableMlJobLinkProps {
jobId: string;
}

const UnavailableMlJobLink: React.FC<UnavailableMlJobLinkProps> = ({ jobId }) => {
const [isPopoverOpen, togglePopover] = useToggle(false);

const button = (
<EuiButtonIcon
iconType="questionInCircle"
onClick={togglePopover}
aria-label={i18n.MACHINE_LEARNING_JOB_NOT_AVAILABLE}
/>
);

return (
<EuiText component="span" color="subdued" size="s">
{jobId}
<EuiPopover button={button} isOpen={isPopoverOpen} closePopover={togglePopover}>
{i18n.MACHINE_LEARNING_JOB_NOT_AVAILABLE}
</EuiPopover>
</EuiText>
);
};

const getRuleTypeDescription = (ruleType: Type) => {
switch (ruleType) {
case 'machine_learning':
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,21 @@ export const MACHINE_LEARNING_JOB_ID_FIELD_LABEL = i18n.translate(
}
);

export const MACHINE_LEARNING_JOB_NOT_AVAILABLE = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleDetails.machineLearning.mlJobNotAvailable',
{
defaultMessage:
'This job is currently unavailable. Please ensure that all related ML integrations are installed and configured.',
}
);

export const OPEN_HELP_POPOVER_ARIA_LABEL = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleDetails.machineLearning.mlJobNotAvailable.openHelpPopoverAriaLabel',
{
defaultMessage: 'Open help popover',
}
);

export const ANOMALY_THRESHOLD_FIELD_LABEL = i18n.translate(
'xpack.securitySolution.detectionEngine.ruleDetails.anomalyThresholdFieldLabel',
{
Expand Down

0 comments on commit b44cff1

Please sign in to comment.