mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[8.14] [Security Solution] - Security solution ES|QL configurable via advanced setting (#181616) (#182517)
# Backport This will backport the following commits from `main` to `8.14`: - [[Security Solution] - Security solution ES|QL configurable via advanced setting (#181616)](https://github.com/elastic/kibana/pull/181616) <!--- Backport version: 8.9.8 --> ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) <!--BACKPORT [{"author":{"name":"Michael Olorunnisola","email":"michael.olorunnisola@elastic.co"},"sourceCommit":{"committedDate":"2024-05-02T17:02:46Z","message":"[Security Solution] - Security solution ES|QL configurable via advanced setting (#181616)\n\n## Summary\r\n\r\nThis PR links the ESQL functionality in security solution to the\r\n`discover:enableESQL` advanced setting. The advanced setting will only\r\nbe present in ESS, but not serverless\r\n\r\nThe way this should work to maintain parity with the rest of Kibana such\r\nas discover and stack rules:\r\n\r\n- By default ES|QL will be enabled across all Kibana\r\n- When the ES|QL advanced setting is disabled:\r\n - Timeline\r\n - ES|QL tab should not be accessible on any newly created timelines\r\n- Existing Timelines with an ES|QL query should still have the tab\r\naccessible\r\n - Rules\r\n- New ES|QL rule should not be available to be created in the *Rule\r\nCreation* workflow\r\n - Existing ES|QL rules should still run and be able to be edited\r\n\r\n\r\n\r\n**Timeline Demo Video:**\r\n\r\n\r\nd5429be9
-de37-43e2-882d-687b3371beb4\r\n\r\n**Rules Demo Video:**\r\n\r\n\r\n\r\n7df2fd11
-bd2b-4e50-ad97-b6e1d0f7867a\r\n\r\n---------\r\n\r\nCo-authored-by: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com>\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"963391ed0f7513c24c4827444feb971e460c53c0","branchLabelMapping":{"^v8.15.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:enhancement","Team:Threat Hunting:Investigations","ci:build-serverless-image","v8.14.0","v8.15.0"],"number":181616,"url":"https://github.com/elastic/kibana/pull/181616","mergeCommit":{"message":"[Security Solution] - Security solution ES|QL configurable via advanced setting (#181616)\n\n## Summary\r\n\r\nThis PR links the ESQL functionality in security solution to the\r\n`discover:enableESQL` advanced setting. The advanced setting will only\r\nbe present in ESS, but not serverless\r\n\r\nThe way this should work to maintain parity with the rest of Kibana such\r\nas discover and stack rules:\r\n\r\n- By default ES|QL will be enabled across all Kibana\r\n- When the ES|QL advanced setting is disabled:\r\n - Timeline\r\n - ES|QL tab should not be accessible on any newly created timelines\r\n- Existing Timelines with an ES|QL query should still have the tab\r\naccessible\r\n - Rules\r\n- New ES|QL rule should not be available to be created in the *Rule\r\nCreation* workflow\r\n - Existing ES|QL rules should still run and be able to be edited\r\n\r\n\r\n\r\n**Timeline Demo Video:**\r\n\r\n\r\nd5429be9
-de37-43e2-882d-687b3371beb4\r\n\r\n**Rules Demo Video:**\r\n\r\n\r\n\r\n7df2fd11
-bd2b-4e50-ad97-b6e1d0f7867a\r\n\r\n---------\r\n\r\nCo-authored-by: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com>\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"963391ed0f7513c24c4827444feb971e460c53c0"}},"sourceBranch":"main","suggestedTargetBranches":["8.14"],"targetPullRequestStates":[{"branch":"8.14","label":"v8.14.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.15.0","labelRegex":"^v8.15.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/181616","number":181616,"mergeCommit":{"message":"[Security Solution] - Security solution ES|QL configurable via advanced setting (#181616)\n\n## Summary\r\n\r\nThis PR links the ESQL functionality in security solution to the\r\n`discover:enableESQL` advanced setting. The advanced setting will only\r\nbe present in ESS, but not serverless\r\n\r\nThe way this should work to maintain parity with the rest of Kibana such\r\nas discover and stack rules:\r\n\r\n- By default ES|QL will be enabled across all Kibana\r\n- When the ES|QL advanced setting is disabled:\r\n - Timeline\r\n - ES|QL tab should not be accessible on any newly created timelines\r\n- Existing Timelines with an ES|QL query should still have the tab\r\naccessible\r\n - Rules\r\n- New ES|QL rule should not be available to be created in the *Rule\r\nCreation* workflow\r\n - Existing ES|QL rules should still run and be able to be edited\r\n\r\n\r\n\r\n**Timeline Demo Video:**\r\n\r\n\r\nd5429be9
-de37-43e2-882d-687b3371beb4\r\n\r\n**Rules Demo Video:**\r\n\r\n\r\n\r\n7df2fd11
-bd2b-4e50-ad97-b6e1d0f7867a\r\n\r\n---------\r\n\r\nCo-authored-by: Vitalii Dmyterko <92328789+vitaliidm@users.noreply.github.com>\r\nCo-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>","sha":"963391ed0f7513c24c4827444feb971e460c53c0"}}]}] BACKPORT--> --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
32fd7e4a25
commit
d6fa87e0d5
13 changed files with 174 additions and 56 deletions
|
@ -23,7 +23,6 @@ xpack.securitySolutionServerless.productTypes:
|
|||
|
||||
xpack.securitySolution.offeringSettings: {
|
||||
ILMEnabled: false, # Index Lifecycle Management (ILM) functionalities disabled, not supported by serverless Elasticsearch
|
||||
ESQLEnabled: false, # ES|QL disabled, not supported by serverless Elasticsearch
|
||||
}
|
||||
|
||||
newsfeed.enabled: true
|
||||
|
|
|
@ -10,10 +10,6 @@ export interface ConfigSettings {
|
|||
* Index Lifecycle Management (ILM) feature enabled.
|
||||
*/
|
||||
ILMEnabled: boolean;
|
||||
/**
|
||||
* ESQL queries enabled.
|
||||
*/
|
||||
ESQLEnabled: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,7 +18,6 @@ export interface ConfigSettings {
|
|||
*/
|
||||
export const defaultSettings: ConfigSettings = Object.freeze({
|
||||
ILMEnabled: true,
|
||||
ESQLEnabled: true,
|
||||
});
|
||||
|
||||
type ConfigSettingsKey = keyof ConfigSettings;
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
/*
|
||||
* 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 { useIsEsqlRuleTypeEnabled } from './use_is_esql_rule_type_enabled';
|
|
@ -1,16 +0,0 @@
|
|||
/*
|
||||
* 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 { useIsExperimentalFeatureEnabled } from '../../hooks/use_experimental_features';
|
||||
import { useKibana } from '../../lib/kibana';
|
||||
|
||||
export const useIsEsqlRuleTypeEnabled = (): boolean => {
|
||||
const isEsqlSettingEnabled = useKibana().services.configSettings.ESQLEnabled;
|
||||
const isEsqlRuleTypeEnabled = !useIsExperimentalFeatureEnabled('esqlRulesDisabled');
|
||||
|
||||
return isEsqlSettingEnabled && isEsqlRuleTypeEnabled;
|
||||
};
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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 { useMemo } from 'react';
|
||||
import { ENABLE_ESQL } from '@kbn/esql-utils';
|
||||
import { useKibana } from '../../lib/kibana';
|
||||
import { useIsExperimentalFeatureEnabled } from '../use_experimental_features';
|
||||
|
||||
/**
|
||||
* This hook combines the checks for esql availability within the security solution
|
||||
* If the advanced setting is disabled, ESQL will not be accessible in the UI for any new timeline or new rule creation workflows
|
||||
* The feature flags are still available to provide users an escape hatch in case of any esql related performance issues
|
||||
*/
|
||||
export const useEsqlAvailability = () => {
|
||||
const { uiSettings } = useKibana().services;
|
||||
const isEsqlAdvancedSettingEnabled = uiSettings?.get(ENABLE_ESQL);
|
||||
const isEsqlRuleTypeEnabled =
|
||||
!useIsExperimentalFeatureEnabled('esqlRulesDisabled') && isEsqlAdvancedSettingEnabled;
|
||||
const isESQLTabInTimelineEnabled =
|
||||
!useIsExperimentalFeatureEnabled('timelineEsqlTabDisabled') && isEsqlAdvancedSettingEnabled;
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
isEsqlAdvancedSettingEnabled,
|
||||
isEsqlRuleTypeEnabled,
|
||||
isESQLTabInTimelineEnabled,
|
||||
}),
|
||||
[isESQLTabInTimelineEnabled, isEsqlAdvancedSettingEnabled, isEsqlRuleTypeEnabled]
|
||||
);
|
||||
};
|
|
@ -10,12 +10,12 @@ import { mount, shallow } from 'enzyme';
|
|||
|
||||
import { SelectRuleType } from '.';
|
||||
import { TestProviders, useFormFieldMock } from '../../../../common/mock';
|
||||
import { useIsEsqlRuleTypeEnabled } from '../../../../common/components/hooks';
|
||||
import { useEsqlAvailability } from '../../../../common/hooks/esql/use_esql_availability';
|
||||
|
||||
jest.mock('../../../../common/components/hooks', () => ({
|
||||
useIsEsqlRuleTypeEnabled: jest.fn().mockReturnValue(true),
|
||||
jest.mock('../../../../common/hooks/esql/use_esql_availability', () => ({
|
||||
useEsqlAvailability: jest.fn().mockReturnValue({ isEsqlRuleTypeEnabled: true }),
|
||||
}));
|
||||
const useIsEsqlRuleTypeEnabledMock = useIsEsqlRuleTypeEnabled as jest.Mock;
|
||||
const useEsqlAvailabilityMock = useEsqlAvailability as jest.Mock;
|
||||
|
||||
describe('SelectRuleType', () => {
|
||||
it('renders correctly', () => {
|
||||
|
@ -185,8 +185,30 @@ describe('SelectRuleType', () => {
|
|||
expect(wrapper.find('[data-test-subj="esqlRuleType"]').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('renders selected card only when in update mode for "esql" and esql feature is disabled', () => {
|
||||
useEsqlAvailabilityMock.mockReturnValueOnce(false);
|
||||
const field = useFormFieldMock<unknown>({ value: 'esql' });
|
||||
const wrapper = mount(
|
||||
<TestProviders>
|
||||
<SelectRuleType
|
||||
describedByIds={[]}
|
||||
field={field}
|
||||
isUpdateView={true}
|
||||
hasValidLicense={true}
|
||||
isMlAdmin={true}
|
||||
/>
|
||||
</TestProviders>
|
||||
);
|
||||
expect(wrapper.find('[data-test-subj="customRuleType"]').exists()).toBeFalsy();
|
||||
expect(wrapper.find('[data-test-subj="machineLearningRuleType"]').exists()).toBeFalsy();
|
||||
expect(wrapper.find('[data-test-subj="thresholdRuleType"]').exists()).toBeFalsy();
|
||||
expect(wrapper.find('[data-test-subj="eqlRuleType"]').exists()).toBeFalsy();
|
||||
expect(wrapper.find('[data-test-subj="threatMatchRuleType"]').exists()).toBeFalsy();
|
||||
expect(wrapper.find('[data-test-subj="esqlRuleType"]').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not render "esql" rule type if esql rule is not enabled', () => {
|
||||
useIsEsqlRuleTypeEnabledMock.mockReturnValueOnce(false);
|
||||
useEsqlAvailabilityMock.mockReturnValueOnce(false);
|
||||
const Component = () => {
|
||||
const field = useFormFieldMock();
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import React, { useCallback, useMemo, memo } from 'react';
|
|||
import { EuiCard, EuiFlexGrid, EuiFlexItem, EuiFormRow, EuiIcon } from '@elastic/eui';
|
||||
|
||||
import type { Type } from '@kbn/securitysolution-io-ts-alerting-types';
|
||||
import { useEsqlAvailability } from '../../../../common/hooks/esql/use_esql_availability';
|
||||
import { isMlRule } from '../../../../../common/machine_learning/helpers';
|
||||
import {
|
||||
isThresholdRule,
|
||||
|
@ -21,7 +22,6 @@ import {
|
|||
import type { FieldHook } from '../../../../shared_imports';
|
||||
import * as i18n from './translations';
|
||||
import { MlCardDescription } from './ml_card_description';
|
||||
import { useIsEsqlRuleTypeEnabled } from '../../../../common/components/hooks';
|
||||
|
||||
interface SelectRuleTypeProps {
|
||||
describedByIds: string[];
|
||||
|
@ -48,7 +48,7 @@ export const SelectRuleType: React.FC<SelectRuleTypeProps> = memo(
|
|||
const setNewTerms = useCallback(() => setType('new_terms'), [setType]);
|
||||
const setEsql = useCallback(() => setType('esql'), [setType]);
|
||||
|
||||
const isEsqlRuleTypeEnabled = useIsEsqlRuleTypeEnabled();
|
||||
const { isEsqlRuleTypeEnabled } = useEsqlAvailability();
|
||||
|
||||
const eqlSelectableConfig = useMemo(
|
||||
() => ({
|
||||
|
@ -194,7 +194,7 @@ export const SelectRuleType: React.FC<SelectRuleTypeProps> = memo(
|
|||
/>
|
||||
</EuiFlexItem>
|
||||
)}
|
||||
{isEsqlRuleTypeEnabled && (!isUpdateView || esqlSelectableConfig.isSelected) && (
|
||||
{((!isUpdateView && isEsqlRuleTypeEnabled) || esqlSelectableConfig.isSelected) && (
|
||||
<EuiFlexItem>
|
||||
<EuiCard
|
||||
data-test-subj="esqlRuleType"
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import { createMockStore, mockGlobalState } from '../../../../common/mock';
|
||||
import { TestProviders } from '../../../../common/mock/test_providers';
|
||||
|
||||
import { TabsContent } from '.';
|
||||
import { TimelineId, TimelineTabs } from '../../../../../common/types/timeline';
|
||||
import { TimelineType } from '../../../../../common/api/timeline';
|
||||
import { useEsqlAvailability } from '../../../../common/hooks/esql/use_esql_availability';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
|
||||
jest.mock('../../../../common/hooks/esql/use_esql_availability', () => ({
|
||||
useEsqlAvailability: jest.fn().mockReturnValue({
|
||||
isESQLTabInTimelineEnabled: true,
|
||||
}),
|
||||
}));
|
||||
|
||||
const useEsqlAvailabilityMock = useEsqlAvailability as jest.Mock;
|
||||
|
||||
describe('Timeline', () => {
|
||||
describe('esql tab', () => {
|
||||
const esqlTabSubj = `timelineTabs-${TimelineTabs.esql}`;
|
||||
const defaultProps = {
|
||||
renderCellValue: () => {},
|
||||
rowRenderers: [],
|
||||
timelineId: TimelineId.test,
|
||||
timelineType: TimelineType.default,
|
||||
timelineDescription: '',
|
||||
};
|
||||
|
||||
it('should show the esql tab', () => {
|
||||
render(
|
||||
<TestProviders>
|
||||
<TabsContent {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
expect(screen.getByTestId(esqlTabSubj)).toBeVisible();
|
||||
});
|
||||
|
||||
it('should not show the esql tab when the advanced setting is disabled', async () => {
|
||||
useEsqlAvailabilityMock.mockReturnValue({
|
||||
isESQLTabInTimelineEnabled: false,
|
||||
});
|
||||
render(
|
||||
<TestProviders>
|
||||
<TabsContent {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId(esqlTabSubj)).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
it('should show the esql tab when the advanced setting is disabled, but an esql query is present', async () => {
|
||||
useEsqlAvailabilityMock.mockReturnValue({
|
||||
isESQLTabInTimelineEnabled: false,
|
||||
});
|
||||
|
||||
const stateWithSavedSearchId = structuredClone(mockGlobalState);
|
||||
stateWithSavedSearchId.timeline.timelineById[TimelineId.test].savedSearchId = 'test-id';
|
||||
const mockStore = createMockStore(stateWithSavedSearchId);
|
||||
|
||||
render(
|
||||
<TestProviders store={mockStore}>
|
||||
<TabsContent {...defaultProps} />
|
||||
</TestProviders>
|
||||
);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(screen.queryByTestId(esqlTabSubj)).toBeVisible();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -13,8 +13,8 @@ import React, { lazy, memo, Suspense, useCallback, useEffect, useMemo, useState
|
|||
import { useDispatch } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { useEsqlAvailability } from '../../../../common/hooks/esql/use_esql_availability';
|
||||
import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features';
|
||||
import { useKibana } from '../../../../common/lib/kibana';
|
||||
import { useAssistantTelemetry } from '../../../../assistant/use_assistant_telemetry';
|
||||
import { useAssistantAvailability } from '../../../../assistant/use_assistant_availability';
|
||||
import type { SessionViewConfig } from '../../../../../common/types';
|
||||
|
@ -43,6 +43,7 @@ import * as i18n from './translations';
|
|||
import { useLicense } from '../../../../common/hooks/use_license';
|
||||
import { TIMELINE_CONVERSATION_TITLE } from '../../../../assistant/content/conversations/translations';
|
||||
import { initializeTimelineSettings } from '../../../store/actions';
|
||||
import { selectTimelineESQLSavedSearchId } from '../../../store/selectors';
|
||||
|
||||
const HideShowContainer = styled.div.attrs<{ $isVisible: boolean; isOverflowYScroll: boolean }>(
|
||||
({ $isVisible = false, isOverflowYScroll = false }) => ({
|
||||
|
@ -109,7 +110,11 @@ const ActiveTimelineTab = memo<ActiveTimelineTabProps>(
|
|||
showTimeline,
|
||||
}) => {
|
||||
const { hasAssistantPrivilege } = useAssistantAvailability();
|
||||
const isEsqlSettingEnabled = useKibana().services.configSettings.ESQLEnabled;
|
||||
const { isESQLTabInTimelineEnabled } = useEsqlAvailability();
|
||||
const timelineESQLSavedSearch = useShallowEqualSelector((state) =>
|
||||
selectTimelineESQLSavedSearchId(state, timelineId)
|
||||
);
|
||||
const shouldShowESQLTab = isESQLTabInTimelineEnabled || timelineESQLSavedSearch != null;
|
||||
const aiAssistantFlyoutMode = useIsExperimentalFeatureEnabled('aiAssistantFlyoutMode');
|
||||
const getTab = useCallback(
|
||||
(tab: TimelineTabs) => {
|
||||
|
@ -177,7 +182,7 @@ const ActiveTimelineTab = memo<ActiveTimelineTabProps>(
|
|||
timelineId={timelineId}
|
||||
/>
|
||||
</HideShowContainer>
|
||||
{showTimeline && isEsqlSettingEnabled && activeTimelineTab === TimelineTabs.esql && (
|
||||
{showTimeline && shouldShowESQLTab && activeTimelineTab === TimelineTabs.esql && (
|
||||
<HideShowContainer
|
||||
$isVisible={true}
|
||||
data-test-subj={`timeline-tab-content-${TimelineTabs.esql}`}
|
||||
|
@ -257,9 +262,7 @@ const TabsContentComponent: React.FC<BasicTimelineTab> = ({
|
|||
sessionViewConfig,
|
||||
timelineDescription,
|
||||
}) => {
|
||||
const isEsqlTabInTimelineDisabled = useIsExperimentalFeatureEnabled('timelineEsqlTabDisabled');
|
||||
const aiAssistantFlyoutMode = useIsExperimentalFeatureEnabled('aiAssistantFlyoutMode');
|
||||
const isEsqlSettingEnabled = useKibana().services.configSettings.ESQLEnabled;
|
||||
const { hasAssistantPrivilege } = useAssistantAvailability();
|
||||
const dispatch = useDispatch();
|
||||
const getActiveTab = useMemo(() => getActiveTabSelector(), []);
|
||||
|
@ -268,9 +271,14 @@ const TabsContentComponent: React.FC<BasicTimelineTab> = ({
|
|||
const getAppNotes = useMemo(() => getNotesSelector(), []);
|
||||
const getTimelineNoteIds = useMemo(() => getNoteIdsSelector(), []);
|
||||
const getTimelinePinnedEventNotes = useMemo(() => getEventIdToNoteIdsSelector(), []);
|
||||
const { isESQLTabInTimelineEnabled } = useEsqlAvailability();
|
||||
const timelineESQLSavedSearch = useShallowEqualSelector((state) =>
|
||||
selectTimelineESQLSavedSearchId(state, timelineId)
|
||||
);
|
||||
|
||||
const activeTab = useShallowEqualSelector((state) => getActiveTab(state, timelineId));
|
||||
const showTimeline = useShallowEqualSelector((state) => getShowTimeline(state, timelineId));
|
||||
const shouldShowESQLTab = isESQLTabInTimelineEnabled || timelineESQLSavedSearch != null;
|
||||
|
||||
const numberOfPinnedEvents = useShallowEqualSelector((state) =>
|
||||
getNumberOfPinnedEvents(state, timelineId)
|
||||
|
@ -373,7 +381,7 @@ const TabsContentComponent: React.FC<BasicTimelineTab> = ({
|
|||
<span>{i18n.QUERY_TAB}</span>
|
||||
{showTimeline && <TimelineEventsCountBadge />}
|
||||
</StyledEuiTab>
|
||||
{!isEsqlTabInTimelineDisabled && isEsqlSettingEnabled && (
|
||||
{shouldShowESQLTab && (
|
||||
<StyledEuiTab
|
||||
data-test-subj={`timelineTabs-${TimelineTabs.esql}`}
|
||||
onClick={setEsqlAsActiveTab}
|
||||
|
|
|
@ -116,6 +116,14 @@ const selectTimelineType = createSelector(selectTimelineById, (timeline) => time
|
|||
*/
|
||||
const selectTimelineKqlQuery = createSelector(selectTimelineById, (timeline) => timeline?.kqlQuery);
|
||||
|
||||
/**
|
||||
* Selector that returns the timeline esql saved search id.
|
||||
*/
|
||||
export const selectTimelineESQLSavedSearchId = createSelector(
|
||||
selectTimelineById,
|
||||
(timeline) => timeline?.savedSearchId
|
||||
);
|
||||
|
||||
/**
|
||||
* Selector that returns the kqlQuery.filterQuery.kuery.expression of a timeline.
|
||||
*/
|
||||
|
|
|
@ -430,7 +430,7 @@ export const previewRulesRoute = async (
|
|||
);
|
||||
break;
|
||||
case 'esql':
|
||||
if (!config.settings.ESQLEnabled || config.experimentalFeatures.esqlRulesDisabled) {
|
||||
if (config.experimentalFeatures.esqlRulesDisabled) {
|
||||
throw Error('ES|QL rule type is not supported');
|
||||
}
|
||||
const esqlAlertType = previewRuleTypeWrapper(createEsqlAlertType(ruleOptions));
|
||||
|
|
|
@ -319,7 +319,7 @@ export class Plugin implements ISecuritySolutionPlugin {
|
|||
const securityRuleTypeWrapper = createSecurityRuleTypeWrapper(securityRuleTypeOptions);
|
||||
|
||||
plugins.alerting.registerType(securityRuleTypeWrapper(createEqlAlertType(ruleOptions)));
|
||||
if (config.settings.ESQLEnabled && !experimentalFeatures.esqlRulesDisabled) {
|
||||
if (!experimentalFeatures.esqlRulesDisabled) {
|
||||
plugins.alerting.registerType(securityRuleTypeWrapper(createEsqlAlertType(ruleOptions)));
|
||||
}
|
||||
plugins.alerting.registerType(
|
||||
|
|
|
@ -20,25 +20,19 @@ describe('Detection ES|QL rules, creation', { tags: ['@serverless'] }, () => {
|
|||
login();
|
||||
});
|
||||
|
||||
it('does not display ES|QL rule on form', function () {
|
||||
it('should display ES|QL rule on form', function () {
|
||||
visit(CREATE_RULE_URL);
|
||||
|
||||
// ensure, page is loaded and rule types are displayed
|
||||
cy.get(NEW_TERMS_TYPE).should('be.visible');
|
||||
cy.get(THRESHOLD_TYPE).should('be.visible');
|
||||
|
||||
// ES|QL rule tile should not be rendered
|
||||
cy.get(ESQL_TYPE).should('not.exist');
|
||||
cy.get(ESQL_TYPE).should('exist');
|
||||
});
|
||||
|
||||
it('does not allow to create rule by API call', function () {
|
||||
it('allow creation rule by API call', function () {
|
||||
createRule(getEsqlRule()).then((response) => {
|
||||
expect(response.status).to.equal(400);
|
||||
|
||||
expect(response.body).to.deep.equal({
|
||||
status_code: 400,
|
||||
message: 'Rule type "siem.esqlRule" is not registered.',
|
||||
});
|
||||
expect(response.status).to.equal(200);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue