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

[Siem migrations] Onboarding UI changes #205734

Merged
merged 27 commits into from
Jan 15, 2025
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
ad9fd90
lookus saved as indices
semd Dec 19, 2024
82b1ae7
agent changes
semd Dec 19, 2024
9cf2019
replace index pattern first
semd Dec 19, 2024
85221a5
uncomment code
semd Dec 20, 2024
4d5a41b
Merge remote-tracking branch 'upstream/main' into 11435/siem_migratio…
semd Dec 20, 2024
f33fb45
type fixes
semd Dec 20, 2024
eea5487
fix test
semd Dec 20, 2024
f758e7d
test fixed
semd Dec 21, 2024
cc221eb
translation agent improvements
semd Dec 23, 2024
be04b80
Merge remote-tracking branch 'upstream/main' into 11435/siem_migratio…
semd Dec 23, 2024
ef87075
fix test
semd Jan 2, 2025
71e67d4
Merge remote-tracking branch 'upstream/main' into 11435/siem_migratio…
semd Jan 2, 2025
2c5e241
Merge branch '11435/siem_migrations/store_lookups' into siem_migratio…
semd Jan 3, 2025
86c2a09
callapsible migration results panel
semd Jan 7, 2025
11d370d
Merge remote-tracking branch 'upstream/main' into siem_migrations/ui_…
semd Jan 7, 2025
85c3c07
Merge remote-tracking branch 'upstream/main' into 11435/siem_migratio…
semd Jan 8, 2025
840cadc
Merge branch '11435/siem_migrations/store_lookups' into siem_migratio…
semd Jan 8, 2025
cee4f09
resolve conflicts
semd Jan 8, 2025
893deb6
unify retry and start API entpoints
semd Jan 8, 2025
46bd9ea
solve conflicts
semd Jan 9, 2025
9bbb6a6
more conflicts solved
semd Jan 9, 2025
f51a1e5
Merge remote-tracking branch 'upstream/main' into siem_migrations/ui_…
semd Jan 13, 2025
ab386b5
add upload button
semd Jan 13, 2025
9d35fd6
solve conflicts
semd Jan 14, 2025
538f359
[CI] Auto-commit changed files from 'yarn openapi:generate'
kibanamachine Jan 15, 2025
90d829a
small changes
semd Jan 15, 2025
fbe7f7f
Merge remote-tracking branch 'refs/remotes/origin/siem_migrations/ui_…
semd Jan 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -388,9 +388,6 @@ import type {
InstallMigrationRulesResponse,
InstallTranslatedMigrationRulesRequestParamsInput,
InstallTranslatedMigrationRulesResponse,
RetryRuleMigrationRequestParamsInput,
RetryRuleMigrationRequestBodyInput,
RetryRuleMigrationResponse,
StartRuleMigrationRequestParamsInput,
StartRuleMigrationRequestBodyInput,
StartRuleMigrationResponse,
Expand Down Expand Up @@ -2033,22 +2030,6 @@ detection engine rules.
})
.catch(catchAxiosErrorFormatAndThrow);
}
/**
* Retries a SIEM rules migration using the migration id provided
*/
async retryRuleMigration(props: RetryRuleMigrationProps) {
this.log.info(`${new Date().toISOString()} Calling API RetryRuleMigration`);
return this.kbnClient
.request<RetryRuleMigrationResponse>({
path: replaceParams('/internal/siem_migrations/rules/{migration_id}/retry', props.params),
headers: {
[ELASTIC_HTTP_VERSION_HEADER]: '1',
},
method: 'PUT',
body: props.body,
})
.catch(catchAxiosErrorFormatAndThrow);
}
async riskEngineGetPrivileges() {
this.log.info(`${new Date().toISOString()} Calling API RiskEngineGetPrivileges`);
return this.kbnClient
Expand Down Expand Up @@ -2600,10 +2581,6 @@ export interface ReadRuleProps {
export interface ResolveTimelineProps {
query: ResolveTimelineRequestQueryInput;
}
export interface RetryRuleMigrationProps {
params: RetryRuleMigrationRequestParamsInput;
body: RetryRuleMigrationRequestBodyInput;
}
export interface RulePreviewProps {
query: RulePreviewRequestQueryInput;
body: RulePreviewRequestBodyInput;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export const SIEM_RULE_MIGRATION_CREATE_PATH =
`${SIEM_RULE_MIGRATIONS_PATH}/{migration_id?}` as const;
export const SIEM_RULE_MIGRATION_PATH = `${SIEM_RULE_MIGRATIONS_PATH}/{migration_id}` as const;
export const SIEM_RULE_MIGRATION_START_PATH = `${SIEM_RULE_MIGRATION_PATH}/start` as const;
export const SIEM_RULE_MIGRATION_RETRY_PATH = `${SIEM_RULE_MIGRATION_PATH}/retry` as const;
export const SIEM_RULE_MIGRATION_STATS_PATH = `${SIEM_RULE_MIGRATION_PATH}/stats` as const;
export const SIEM_RULE_MIGRATION_TRANSLATION_STATS_PATH =
`${SIEM_RULE_MIGRATION_PATH}/translation_stats` as const;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,28 +231,6 @@ export const InstallTranslatedMigrationRulesResponse = z.object({
installed: z.boolean(),
});

export type RetryRuleMigrationRequestParams = z.infer<typeof RetryRuleMigrationRequestParams>;
export const RetryRuleMigrationRequestParams = z.object({
migration_id: NonEmptyString,
});
export type RetryRuleMigrationRequestParamsInput = z.input<typeof RetryRuleMigrationRequestParams>;

export type RetryRuleMigrationRequestBody = z.infer<typeof RetryRuleMigrationRequestBody>;
export const RetryRuleMigrationRequestBody = z.object({
connector_id: ConnectorId,
langsmith_options: LangSmithOptions.optional(),
filter: RuleMigrationRetryFilter.optional(),
});
export type RetryRuleMigrationRequestBodyInput = z.input<typeof RetryRuleMigrationRequestBody>;

export type RetryRuleMigrationResponse = z.infer<typeof RetryRuleMigrationResponse>;
export const RetryRuleMigrationResponse = z.object({
/**
* Indicates the migration retry has been started. `false` means the migration does not need to be retried.
*/
started: z.boolean(),
});

export type StartRuleMigrationRequestParams = z.infer<typeof StartRuleMigrationRequestParams>;
export const StartRuleMigrationRequestParams = z.object({
migration_id: NonEmptyString,
Expand All @@ -263,6 +241,10 @@ export type StartRuleMigrationRequestBody = z.infer<typeof StartRuleMigrationReq
export const StartRuleMigrationRequestBody = z.object({
connector_id: ConnectorId,
langsmith_options: LangSmithOptions.optional(),
/**
* The optional indicator to retry the rule translation based on this filter criteria
*/
retry: RuleMigrationRetryFilter.optional(),
});
export type StartRuleMigrationRequestBodyInput = z.input<typeof StartRuleMigrationRequestBody>;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ paths:
$ref: '../../common.schema.yaml#/components/schemas/ConnectorId'
langsmith_options:
$ref: '../../common.schema.yaml#/components/schemas/LangSmithOptions'
retry:
$ref: '../../rule_migration.schema.yaml#/components/schemas/RuleMigrationRetryFilter'
description: The optional indicator to retry the rule translation based on this filter criteria
responses:
200:
description: Indicates the migration start request has been processed successfully.
Expand All @@ -336,53 +339,6 @@ paths:
204:
description: Indicates the migration id was not found.

/internal/siem_migrations/rules/{migration_id}/retry:
put:
summary: Retries a rule migration
operationId: RetryRuleMigration
x-codegen-enabled: true
x-internal: true
description: Retries a SIEM rules migration using the migration id provided
tags:
- SIEM Rule Migrations
parameters:
- name: migration_id
in: path
required: true
schema:
description: The migration id to retry
$ref: '../../../../../common/api/model/primitives.schema.yaml#/components/schemas/NonEmptyString'
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- connector_id
properties:
connector_id:
$ref: '../../common.schema.yaml#/components/schemas/ConnectorId'
langsmith_options:
$ref: '../../common.schema.yaml#/components/schemas/LangSmithOptions'
filter:
$ref: '../../rule_migration.schema.yaml#/components/schemas/RuleMigrationRetryFilter'
responses:
200:
description: Indicates the migration retry request has been processed successfully.
content:
application/json:
schema:
type: object
required:
- started
properties:
started:
type: boolean
description: Indicates the migration retry has been started. `false` means the migration does not need to be retried.
204:
description: Indicates the migration id was not found.

/internal/siem_migrations/rules/{migration_id}/stats:
get:
summary: Gets a rule migration task stats
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,6 @@
*/

import { z } from '@kbn/zod';
import { isNonEmptyString } from '@kbn/zod-helpers';

/**
* A string that does not contain only whitespace characters
*/
export type NonEmptyString = z.infer<typeof NonEmptyString>;
export const NonEmptyString = z.string().min(1).superRefine(isNonEmptyString);

/**
* The GenAI connector id to use.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,10 @@ paths: {}
components:
x-codegen-enabled: true
schemas:
NonEmptyString:
type: string
format: nonempty
minLength: 1
description: A string that does not contain only whitespace characters
ConnectorId:
type: string
description: The GenAI connector id to use.

LangSmithOptions:
type: object
description: The LangSmith options object.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@
*/

import React from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLink } from '@elastic/eui';
import { OnboardingCardContentPanel } from '../../common/card_content_panel';
import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiLink, EuiPanel } from '@elastic/eui';
import { CardCallOut } from '../../common/card_callout';
import * as i18n from './translations';

Expand All @@ -17,7 +16,7 @@ interface MissingAIConnectorCalloutProps {

export const MissingAIConnectorCallout = React.memo<MissingAIConnectorCalloutProps>(
({ onExpandAiConnectorsCard }) => (
<OnboardingCardContentPanel paddingSize="none">
<EuiPanel hasShadow={false} paddingSize="none">
<CardCallOut
color="warning"
text={i18n.START_MIGRATION_CARD_CONNECTOR_MISSING_TEXT}
Expand All @@ -32,7 +31,7 @@ export const MissingAIConnectorCallout = React.memo<MissingAIConnectorCalloutPro
</EuiLink>
}
/>
</OnboardingCardContentPanel>
</EuiPanel>
)
);
MissingAIConnectorCallout.displayName = 'MissingAIConnectorCallout';
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* 2.0.
*/

import React from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
import { SiemMigrationTaskStatus } from '../../../../../../../common/siem_migrations/constants';
import type { RuleMigrationStats } from '../../../../../../siem_migrations/rules/types';
import { UploadRulesPanel } from './upload_rules_panel';
Expand All @@ -22,24 +22,52 @@ export interface RuleMigrationsPanelsProps {
}
export const RuleMigrationsPanels = React.memo<RuleMigrationsPanelsProps>(
({ migrationsStats, isConnectorsCardComplete, expandConnectorsCard }) => {
if (migrationsStats.length === 0) {
return isConnectorsCardComplete ? (
<UploadRulesPanel />
) : (
<MissingAIConnectorCallout onExpandAiConnectorsCard={expandConnectorsCard} />
);
}
const latestMigrationsStats = useMemo(
() => migrationsStats.slice().reverse(),
[migrationsStats]
);

const [expandedCardId, setExpandedCardId] = useState<string | undefined>(() => {
if (latestMigrationsStats[0]?.status === SiemMigrationTaskStatus.FINISHED) {
return latestMigrationsStats[0]?.id;
}
return undefined;
});

useEffect(() => {
if (!expandedCardId && latestMigrationsStats.length > 0) {
const runningMigration = latestMigrationsStats.find(
({ status }) => status === SiemMigrationTaskStatus.RUNNING
);
if (runningMigration) {
setExpandedCardId(runningMigration.id); // Set the next migration to be expanded when it finishes
}
}
}, [latestMigrationsStats, expandedCardId]);

const getOnToggleCollapsed = useCallback(
(id: string) => (isCollapsed: boolean) => {
setExpandedCardId(isCollapsed ? undefined : id);
},
[]
);

return (
<EuiFlexGroup direction="column" gutterSize="m">
<EuiFlexItem grow={false}>
{isConnectorsCardComplete ? (
<UploadRulesPanel isUploadMore />
) : (
<MissingAIConnectorCallout onExpandAiConnectorsCard={expandConnectorsCard} />
{!isConnectorsCardComplete && (
<>
<MissingAIConnectorCallout onExpandAiConnectorsCard={expandConnectorsCard} />
<EuiSpacer size="s" />
</>
)}
<UploadRulesPanel
isUploadMore={latestMigrationsStats.length > 0}
isDisabled={!isConnectorsCardComplete}
/>
</EuiFlexItem>
{migrationsStats.map((migrationStats) => (

{latestMigrationsStats.map((migrationStats) => (
<EuiFlexItem grow={false} key={migrationStats.id}>
{migrationStats.status === SiemMigrationTaskStatus.READY && (
<MigrationReadyPanel migrationStats={migrationStats} />
Expand All @@ -48,7 +76,11 @@ export const RuleMigrationsPanels = React.memo<RuleMigrationsPanelsProps>(
<MigrationProgressPanel migrationStats={migrationStats} />
)}
{migrationStats.status === SiemMigrationTaskStatus.FINISHED && (
<MigrationResultPanel migrationStats={migrationStats} />
<MigrationResultPanel
migrationStats={migrationStats}
isCollapsed={migrationStats.id !== expandedCardId}
onToggleCollapsed={getOnToggleCollapsed(migrationStats.id)}
/>
)}
</EuiFlexItem>
))}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ export const START_MIGRATION_CARD_FOOTER_NOTE = i18n.translate(
export const START_MIGRATION_CARD_CONNECTOR_MISSING_TEXT = i18n.translate(
'xpack.securitySolution.onboarding.startMigration.connectorMissingText',
{
defaultMessage: 'Rule migrations require an AI connector to be configured.',
defaultMessage:
'You need an LLM connector to power SIEM rule migration. Set one up or choose an existing one to get started.',
}
);
export const START_MIGRATION_CARD_CONNECTOR_MISSING_BUTTON = i18n.translate(
'xpack.securitySolution.onboarding.startMigration.connectorMissingText',
{ defaultMessage: 'AI provider step' }
{ defaultMessage: 'Set up AI Connector' }
);

export const START_MIGRATION_CARD_UPLOAD_TITLE = i18n.translate(
Expand Down
Loading