Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -461,6 +461,8 @@ export const getDocLinks = ({ kibanaBranch, buildFlavor }: GetDocLinkOptions): D
signalsMigrationApi: `${SECURITY_SOLUTION_DOCS}signals-migration-api.html`,
legacyEndpointManagementApiDeprecations: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-199598`,
legacyRuleManagementBulkApiDeprecations: `${KIBANA_DOCS}breaking-changes-summary.html#breaking-207091`,
siemMigrations: `${SECURITY_SOLUTION_DOCS}siem-migration.html`,
llmPerformanceMatrix: `${SECURITY_SOLUTION_DOCS}llm-performance-matrix.html`,
},
query: {
eql: `${ELASTICSEARCH_DOCS}eql.html`,
Expand Down
2 changes: 2 additions & 0 deletions src/platform/packages/shared/kbn-doc-links/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ export interface DocLinks {
readonly signalsMigrationApi: string;
readonly legacyEndpointManagementApiDeprecations: string;
readonly legacyRuleManagementBulkApiDeprecations: string;
readonly siemMigrations: string;
readonly llmPerformanceMatrix: string;
};
readonly query: {
readonly eql: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,31 @@ import { EuiText, useEuiTheme, COLOR_MODES_STANDARD, type EuiTextProps } from '@
export interface PanelTextProps extends PropsWithChildren<EuiTextProps> {
subdued?: true;
semiBold?: true;
cursive?: true;
}
export const PanelText = React.memo<PanelTextProps>(({ children, subdued, semiBold, ...props }) => {
const { euiTheme, colorMode } = useEuiTheme();
const isDarkMode = colorMode === COLOR_MODES_STANDARD.dark;
export const PanelText = React.memo<PanelTextProps>(
({ children, subdued, semiBold, cursive, ...props }) => {
const { euiTheme, colorMode } = useEuiTheme();
const isDarkMode = colorMode === COLOR_MODES_STANDARD.dark;

let color;
if (subdued && !isDarkMode) {
color = 'subdued';
}
let color;
if (subdued && !isDarkMode) {
color = 'subdued';
}

const style: CSSInterpolation = {};
if (semiBold) {
style.fontWeight = euiTheme.font.weight.semiBold;
}
const style: CSSInterpolation = {};
if (semiBold) {
style.fontWeight = euiTheme.font.weight.semiBold;
}
if (cursive) {
style.fontStyle = 'italic';
}

return (
<EuiText {...props} color={color} className={css(style)}>
{children}
</EuiText>
);
});
return (
<EuiText {...props} color={color} className={css(style)}>
{children}
</EuiText>
);
}
);
PanelText.displayName = 'PanelText';
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import React from 'react';
import type { OnboardingCardConfig } from '../../../../types';
import { OnboardingCardId } from '../../../../constants';
import { ALERTS_CARD_TITLE } from './translations';
import { getCardIcon } from '../common/card_icon';
import alertsIcon from './images/alerts_icon.png';
import alertsDarkIcon from './images/alerts_icon_dark.png';

export const alertsCardConfig: OnboardingCardConfig = {
id: OnboardingCardId.alerts,
title: ALERTS_CARD_TITLE,
icon: () => getCardIcon(OnboardingCardId.alerts),
icon: alertsIcon,
iconDark: alertsDarkIcon,
Component: React.lazy(
() =>
import(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const useCardCallOutStyles = () => {
const { euiTheme } = useEuiTheme();
return css`
padding: ${euiTheme.size.s};
border: ${euiTheme.border.width.thin} solid ${euiTheme.colors.backgroundBaseSubdued};
border: ${euiTheme.border.width.thin} solid ${euiTheme.colors.borderBaseSubdued};
border-radius: ${euiTheme.size.s};
`;
};

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,18 @@ export const ConnectorSelectorPanel = React.memo<ConnectorSelectorPanelProps>(
);

useEffect(() => {
if (connectors.length === 1) {
if (selectedConnectorId || !connectors.length) {
return;
}
const inferenceConnector = connectors.find(
({ actionTypeId }) => actionTypeId === '.inference'
);
if (inferenceConnector) {
onConnectorSelected(inferenceConnector);
} else if (connectors.length === 1) {
onConnectorSelected(connectors[0]);
}
}, [connectors, onConnectorSelected]);
}, [selectedConnectorId, connectors, onConnectorSelected]);

const connectorOptions = useMemo(
() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ import React from 'react';
import type { OnboardingCardConfig } from '../../../../types';
import { OnboardingCardId } from '../../../../constants';
import { DASHBOARDS_CARD_TITLE } from './translations';
import { getCardIcon } from '../common/card_icon';
import dashboardsIcon from './images/dashboards_icon.png';
import dashboardsDarkIcon from './images/dashboards_icon_dark.png';

export const dashboardsCardConfig: OnboardingCardConfig = {
id: OnboardingCardId.dashboards,
title: DASHBOARDS_CARD_TITLE,
icon: () => getCardIcon(OnboardingCardId.dashboards),
icon: dashboardsIcon,
iconDark: dashboardsDarkIcon,
Comment thread
semd marked this conversation as resolved.
Component: React.lazy(
() =>
import(
/* webpackChunkName: "onboarding_dashboards_card" */
'./dashboards_card'
)
),
capabilitiesRequired: ['dashboard_v2.show'],
capabilitiesRequired: 'dashboard_v2.show',
};
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ import type { OnboardingCardConfig } from '../../../../types';
import { checkIntegrationsCardComplete } from './integrations_check_complete';
import { OnboardingCardId } from '../../../../constants';
import type { IntegrationCardMetadata } from './types';
import { getCardIcon } from '../common/card_icon';
import integrationsIcon from './images/integrations_icon.png';
import integrationsDarkIcon from './images/integrations_icon_dark.png';

export const integrationsCardConfig: OnboardingCardConfig<IntegrationCardMetadata> = {
id: OnboardingCardId.integrations,
title: i18n.translate('xpack.securitySolution.onboarding.integrationsCard.title', {
defaultMessage: 'Add data with integrations',
}),
icon: () => getCardIcon(OnboardingCardId.integrations),
icon: integrationsIcon,
iconDark: integrationsDarkIcon,
Component: React.lazy(
() =>
import(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,14 @@ import type { OnboardingCardConfig } from '../../../../types';
import { OnboardingCardId } from '../../../../constants';
import { RULES_CARD_TITLE } from './translations';
import { checkRulesComplete } from './rules_check_complete';
import { getCardIcon } from '../common/card_icon';
import rulesIcon from './images/rules_icon.png';
import rulesDarkIcon from './images/rules_icon_dark.png';

export const rulesCardConfig: OnboardingCardConfig = {
id: OnboardingCardId.rules,
title: RULES_CARD_TITLE,
icon: () => getCardIcon(OnboardingCardId.rules),
icon: rulesIcon,
iconDark: rulesDarkIcon,
Component: React.lazy(
() =>
import(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
* 2.0.
*/

import React, { useCallback } from 'react';
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React, { useCallback, useMemo } from 'react';
import { EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
import { CenteredLoadingSpinner } from '../../../../../../common/components/centered_loading_spinner';
import { useKibana } from '../../../../../../common/lib/kibana/kibana_react';
import { useDefinedLocalStorage } from '../../../../hooks/use_stored_state';
Expand All @@ -19,6 +20,26 @@ import { ConnectorsMissingPrivilegesCallOut } from '../../common/connectors/miss
import type { AIConnector } from '../../common/connectors/types';
import type { AIConnectorCardMetadata } from './types';

const LlmPerformanceMatrixDocsLink = React.memo<{ text: string }>(({ text }) => {
const { llmPerformanceMatrix } = useKibana().services.docLinks.links.securitySolution;
return (
<EuiLink href={llmPerformanceMatrix} target="_blank">
{text}
</EuiLink>
);
});
LlmPerformanceMatrixDocsLink.displayName = 'LlmPerformanceMatrixDocsLink';

const SiemMigrationDocsLink = React.memo<{ text: string }>(({ text }) => {
const { siemMigrations } = useKibana().services.docLinks.links.securitySolution;
return (
<EuiLink href={siemMigrations} target="_blank">
{text}
</EuiLink>
);
});
SiemMigrationDocsLink.displayName = 'SiemMigrationDocsLink';

export const AIConnectorCard: OnboardingCardComponent<AIConnectorCardMetadata> = ({
checkCompleteMetadata,
checkComplete,
Expand All @@ -38,6 +59,14 @@ export const AIConnectorCard: OnboardingCardComponent<AIConnectorCardMetadata> =
[setComplete, setStoredConnectorId, siemMigrations]
);

const isInferenceConnector = useMemo(() => {
if (!checkCompleteMetadata?.connectors?.length || !storedConnectorId) {
return false;
}
const connector = checkCompleteMetadata.connectors.find((c) => c.id === storedConnectorId);
return connector?.actionTypeId === '.inference' ?? false;
}, [checkCompleteMetadata, storedConnectorId]);

if (!checkCompleteMetadata) {
return (
<OnboardingCardContentPanel>
Expand All @@ -53,7 +82,28 @@ export const AIConnectorCard: OnboardingCardComponent<AIConnectorCardMetadata> =
{canExecuteConnectors ? (
<EuiFlexGroup direction="column">
<EuiFlexItem grow={false}>
<CardSubduedText size="s">{i18n.AI_CONNECTOR_CARD_DESCRIPTION}</CardSubduedText>
<CardSubduedText size="s">
{i18n.AI_CONNECTOR_CARD_DESCRIPTION_START}
{isInferenceConnector ? (
<FormattedMessage
id="xpack.securitySolution.onboarding.aiConnectorCardInferenceDescription"
defaultMessage="The Elastic-provided connector is selected by default. You can configure another connector and model if you prefer. Learn more about {docsLink} and performance with our {llmMatrixLink}"
values={{
llmMatrixLink: <LlmPerformanceMatrixDocsLink text={i18n.LLM_MATRIX_LINK} />,
docsLink: <SiemMigrationDocsLink text={i18n.AI_POWERED_MIGRATIONS_LINK} />,
}}
/>
) : (
<FormattedMessage
id="xpack.securitySolution.onboarding.aiConnectorCardNotInferenceDescription"
defaultMessage="Refer to the {llmMatrixLink} for information about which models perform best. {docsLink} about AI-powered SIEM migration."
values={{
llmMatrixLink: <LlmPerformanceMatrixDocsLink text={i18n.LLM_MATRIX_LINK} />,
docsLink: <SiemMigrationDocsLink text={i18n.LEARN_MORE_LINK} />,
}}
/>
)}
</CardSubduedText>
</EuiFlexItem>
<EuiFlexItem>
<ConnectorCards
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,30 @@ export const AI_CONNECTOR_CARD_TITLE = i18n.translate(
}
);

export const AI_CONNECTOR_CARD_DESCRIPTION = i18n.translate(
'xpack.securitySolution.onboarding.aiConnector.description',
export const AI_CONNECTOR_CARD_DESCRIPTION_START = i18n.translate(
'xpack.securitySolution.onboarding.aiConnector.descriptionStart',
{ defaultMessage: 'This feature relies on an AI connector for rule translation. ' }
);

export const AI_CONNECTOR_CARD_DESCRIPTION_INFERENCE_CONNECTOR = i18n.translate(
'xpack.securitySolution.onboarding.aiConnector.descriptionInferenceConnector',
{
defaultMessage:
'Choose and configure any AI provider available to start a SIEM rules migration.',
'The Elastic-provided connector is selected by default. You can configure another connector and model if you prefer. ',
}
);

export const LLM_MATRIX_LINK = i18n.translate(
'xpack.securitySolution.onboarding.aiConnector.llmMatrixLink',
{ defaultMessage: 'LLM performance matrix' }
);

export const AI_POWERED_MIGRATIONS_LINK = i18n.translate(
'xpack.securitySolution.onboarding.aiConnector.siemMigrationLink',
{ defaultMessage: 'AI-powered SIEM migration' }
);

export const LEARN_MORE_LINK = i18n.translate(
'xpack.securitySolution.onboarding.aiConnector.learnMoreLink',
{ defaultMessage: 'Learn more' }
);
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ import { OnboardingCardId } from '../../../../../constants';
import { START_MIGRATION_CARD_TITLE } from './translations';
import type { StartMigrationCardMetadata } from './types';
import { checkStartMigrationCardComplete } from './start_migration_check_complete';
import { getCardIcon } from '../../common/card_icon';
import startMigrationIcon from './images/start_migration_icon.png';
import startMigrationDarkIcon from './images/start_migration_icon_dark.png';

export const startMigrationCardConfig: OnboardingCardConfig<StartMigrationCardMetadata> = {
id: OnboardingCardId.siemMigrationsStart,
id: OnboardingCardId.siemMigrationsRules,
title: START_MIGRATION_CARD_TITLE,
icon: () => getCardIcon(OnboardingCardId.siemMigrationsStart),
badge: 'tech_preview',
icon: startMigrationIcon,
iconDark: startMigrationDarkIcon,
Component: React.lazy(
() =>
import(
Expand Down
Loading