= ({ basePath }) => (
),
diff --git a/x-pack/plugins/ml/public/application/services/anomaly_explorer_charts_service.ts b/x-pack/plugins/ml/public/application/services/anomaly_explorer_charts_service.ts
index afad043fcc4d13..97ddefac860f2d 100644
--- a/x-pack/plugins/ml/public/application/services/anomaly_explorer_charts_service.ts
+++ b/x-pack/plugins/ml/public/application/services/anomaly_explorer_charts_service.ts
@@ -225,13 +225,20 @@ export class AnomalyExplorerChartsService {
chartRange.min = chartRange.min + maxBucketSpanMs;
}
+ // When used as an embeddable, selectedEarliestMs is the start date on the time picker,
+ // which may be earlier than the time of the first point plotted in the chart (as we plot
+ // the first full bucket with a start date no earlier than the start).
+ const selectedEarliestBucketCeil = boundsMin
+ ? Math.ceil(Math.max(selectedEarliestMs, boundsMin) / maxBucketSpanMs) * maxBucketSpanMs
+ : Math.ceil(selectedEarliestMs / maxBucketSpanMs) * maxBucketSpanMs;
+
const selectedLatestBucketStart = boundsMax
? Math.floor(Math.min(selectedLatestMs, boundsMax) / maxBucketSpanMs) * maxBucketSpanMs
: Math.floor(selectedLatestMs / maxBucketSpanMs) * maxBucketSpanMs;
if (
- (chartRange.min > selectedEarliestMs || chartRange.max < selectedLatestBucketStart) &&
- chartRange.max - chartRange.min < selectedLatestBucketStart - selectedEarliestMs
+ (chartRange.min > selectedEarliestBucketCeil || chartRange.max < selectedLatestBucketStart) &&
+ chartRange.max - chartRange.min < selectedLatestBucketStart - selectedEarliestBucketCeil
) {
tooManyBuckets = true;
}
diff --git a/x-pack/plugins/ml/public/application/services/anomaly_timeline_service.ts b/x-pack/plugins/ml/public/application/services/anomaly_timeline_service.ts
index e11eb4048c374b..6f2b5417eff5fb 100644
--- a/x-pack/plugins/ml/public/application/services/anomaly_timeline_service.ts
+++ b/x-pack/plugins/ml/public/application/services/anomaly_timeline_service.ts
@@ -25,6 +25,8 @@ import {
} from '../explorer/explorer_utils';
import { OVERALL_LABEL, VIEW_BY_JOB_LABEL } from '../explorer/explorer_constants';
import { MlResultsService } from './results_service';
+import { EntityField } from '../../../common/util/anomaly_utils';
+import { InfluencersFilterQuery } from '../../../common/types/es_client';
/**
* Service for retrieving anomaly swim lanes data.
@@ -241,7 +243,9 @@ export class AnomalyTimelineService {
swimlaneLimit: number,
perPage: number,
fromPage: number,
- swimlaneContainerWidth: number
+ swimlaneContainerWidth: number,
+ selectionInfluencers: EntityField[],
+ influencersFilterQuery: InfluencersFilterQuery
) {
const selectedJobIds = selectedJobs.map((d) => d.id);
@@ -254,7 +258,9 @@ export class AnomalyTimelineService {
latestMs,
swimlaneLimit,
perPage,
- fromPage
+ fromPage,
+ selectionInfluencers,
+ influencersFilterQuery
);
if (resp.influencers[viewBySwimlaneFieldName] === undefined) {
return [];
@@ -276,6 +282,8 @@ export class AnomalyTimelineService {
earliestMs,
latestMs,
this.getSwimlaneBucketInterval(selectedJobs, swimlaneContainerWidth).asMilliseconds(),
+ perPage,
+ fromPage,
swimlaneLimit
);
return Object.keys(resp.results);
diff --git a/x-pack/plugins/ml/public/application/services/ml_api_service/results.ts b/x-pack/plugins/ml/public/application/services/ml_api_service/results.ts
index 25ef36782207f1..a9f6dbb45f6e34 100644
--- a/x-pack/plugins/ml/public/application/services/ml_api_service/results.ts
+++ b/x-pack/plugins/ml/public/application/services/ml_api_service/results.ts
@@ -16,6 +16,11 @@ import { JobId } from '../../../../common/types/anomaly_detection_jobs';
import { JOB_ID, PARTITION_FIELD_VALUE } from '../../../../common/constants/anomalies';
import { PartitionFieldsDefinition } from '../results_service/result_service_rx';
import { PartitionFieldsConfig } from '../../../../common/types/storage';
+import {
+ ESSearchRequest,
+ ESSearchResponse,
+} from '../../../../../../../src/core/types/elasticsearch';
+import { MLAnomalyDoc } from '../../../../common/types/anomalies';
export const resultsApiProvider = (httpService: HttpService) => ({
getAnomaliesTableData(
@@ -112,18 +117,18 @@ export const resultsApiProvider = (httpService: HttpService) => ({
});
},
- anomalySearch(query: any, jobIds: string[]) {
+ anomalySearch(query: ESSearchRequest, jobIds: string[]) {
const body = JSON.stringify({ query, jobIds });
- return httpService.http({
+ return httpService.http>({
path: `${basePath()}/results/anomaly_search`,
method: 'POST',
body,
});
},
- anomalySearch$(query: any, jobIds: string[]) {
+ anomalySearch$(query: ESSearchRequest, jobIds: string[]) {
const body = JSON.stringify({ query, jobIds });
- return httpService.http$({
+ return httpService.http$>({
path: `${basePath()}/results/anomaly_search`,
method: 'POST',
body,
diff --git a/x-pack/plugins/ml/public/application/services/results_service/results_service.d.ts b/x-pack/plugins/ml/public/application/services/results_service/results_service.d.ts
index ea07d32bfff1d0..1848b13cb5a1f9 100644
--- a/x-pack/plugins/ml/public/application/services/results_service/results_service.d.ts
+++ b/x-pack/plugins/ml/public/application/services/results_service/results_service.d.ts
@@ -23,7 +23,8 @@ export function resultsServiceProvider(
intervalMs: number,
perPage?: number,
fromPage?: number,
- swimLaneSeverity?: number
+ swimLaneSeverity?: number,
+ influencersFilterQuery?: InfluencersFilterQuery
): Promise;
getTopInfluencers(
selectedJobIds: string[],
@@ -32,7 +33,7 @@ export function resultsServiceProvider(
maxFieldValues: number,
perPage?: number,
fromPage?: number,
- influencers?: any[],
+ influencers?: EntityField[],
influencersFilterQuery?: InfluencersFilterQuery
): Promise;
getTopInfluencerValues(): Promise;
diff --git a/x-pack/plugins/monitoring/public/plugin.ts b/x-pack/plugins/monitoring/public/plugin.ts
index a5b7d4906b5869..9f84165a27ba9f 100644
--- a/x-pack/plugins/monitoring/public/plugin.ts
+++ b/x-pack/plugins/monitoring/public/plugin.ts
@@ -93,7 +93,10 @@ export class MonitoringPlugin
category: DEFAULT_APP_CATEGORIES.management,
mount: async (params: AppMountParameters) => {
const [coreStart, pluginsStart] = await core.getStartServices();
- const { AngularApp } = await import('./angular');
+ const [, { AngularApp }] = await Promise.all([
+ pluginsStart.kibanaLegacy.loadAngularBootstrap(),
+ import('./angular'),
+ ]);
const deps: MonitoringStartPluginDependencies = {
navigation: pluginsStart.navigation,
kibanaLegacy: pluginsStart.kibanaLegacy,
diff --git a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx
index d3b0e38a5e033b..bf4c97d63d74ca 100644
--- a/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx
+++ b/x-pack/plugins/osquery/public/action_results/action_results_summary.tsx
@@ -8,15 +8,13 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
import { i18n } from '@kbn/i18n';
-import { EuiLink, EuiInMemoryTable, EuiCodeBlock } from '@elastic/eui';
+import { EuiInMemoryTable, EuiCodeBlock } from '@elastic/eui';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
-import { PLUGIN_ID } from '../../../fleet/common';
-import { pagePathGetters } from '../../../fleet/public';
+import { AgentIdToName } from '../agents/agent_id_to_name';
import { useActionResults } from './use_action_results';
import { useAllResults } from '../results/use_all_results';
import { Direction } from '../../common/search_strategy';
-import { useKibana } from '../common/lib/kibana';
interface ActionResultsSummaryProps {
actionId: string;
@@ -35,7 +33,6 @@ const ActionResultsSummaryComponent: React.FC = ({
expirationDate,
agentIds,
}) => {
- const getUrlForApp = useKibana().services.application.getUrlForApp;
// @ts-expect-error update types
const [pageIndex, setPageIndex] = useState(0);
// @ts-expect-error update types
@@ -70,20 +67,7 @@ const ActionResultsSummaryComponent: React.FC = ({
isLive,
});
- const renderAgentIdColumn = useCallback(
- (agentId) => (
-
- {agentId}
-
- ),
- [getUrlForApp]
- );
+ const renderAgentIdColumn = useCallback((agentId) => , []);
const renderRowsColumn = useCallback(
(_, item) => {
diff --git a/x-pack/plugins/osquery/public/actions/actions_table.tsx b/x-pack/plugins/osquery/public/actions/actions_table.tsx
index 0ee928ad8aa147..045c1f67b070da 100644
--- a/x-pack/plugins/osquery/public/actions/actions_table.tsx
+++ b/x-pack/plugins/osquery/public/actions/actions_table.tsx
@@ -9,6 +9,7 @@ import { isArray } from 'lodash';
import { i18n } from '@kbn/i18n';
import { EuiBasicTable, EuiButtonIcon, EuiCodeBlock, formatDate } from '@elastic/eui';
import React, { useState, useCallback, useMemo } from 'react';
+import { useHistory } from 'react-router-dom';
import { useAllActions } from './use_all_actions';
import { Direction } from '../../common/search_strategy';
@@ -27,6 +28,7 @@ const ActionTableResultsButton = React.memo(({ ac
ActionTableResultsButton.displayName = 'ActionTableResultsButton';
const ActionsTableComponent = () => {
+ const { push } = useHistory();
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(20);
@@ -67,6 +69,16 @@ const ActionsTableComponent = () => {
[]
);
+ const handlePlayClick = useCallback(
+ (item) =>
+ push('/live_queries/new', {
+ form: {
+ query: item._source?.data?.query,
+ },
+ }),
+ [push]
+ );
+
const columns = useMemo(
() => [
{
@@ -106,6 +118,11 @@ const ActionsTableComponent = () => {
defaultMessage: 'View details',
}),
actions: [
+ {
+ type: 'icon',
+ icon: 'play',
+ onClick: handlePlayClick,
+ },
{
render: renderActionsColumn,
},
@@ -113,6 +130,7 @@ const ActionsTableComponent = () => {
},
],
[
+ handlePlayClick,
renderActionsColumn,
renderAgentsColumn,
renderCreatedByColumn,
@@ -135,6 +153,7 @@ const ActionsTableComponent = () => {
= ({ agentId }) => {
+ const getUrlForApp = useKibana().services.application.getUrlForApp;
+ const { data } = useAgentDetails({ agentId });
+
+ return (
+
+ {data?.item.local_metadata.host.name ?? agentId}
+
+ );
+};
+
+export const AgentIdToName = React.memo(AgentIdToNameComponent);
diff --git a/x-pack/plugins/osquery/public/agents/agents_table.tsx b/x-pack/plugins/osquery/public/agents/agents_table.tsx
index 7e8f49c051614d..53e2ce1d534204 100644
--- a/x-pack/plugins/osquery/public/agents/agents_table.tsx
+++ b/x-pack/plugins/osquery/public/agents/agents_table.tsx
@@ -21,7 +21,12 @@ import {
generateAgentSelection,
} from './helpers';
-import { SELECT_AGENT_LABEL, generateSelectedAgentsMessage } from './translations';
+import {
+ SELECT_AGENT_LABEL,
+ generateSelectedAgentsMessage,
+ ALL_AGENTS_LABEL,
+ AGENT_POLICY_LABEL,
+} from './translations';
import {
AGENT_GROUP_KEY,
@@ -72,8 +77,17 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh
useEffect(() => {
if (agentSelection && !defaultValueInitialized.current && options.length) {
- if (agentSelection.policiesSelected) {
- const policyOptions = find(['label', 'Policy'], options);
+ if (agentSelection.allAgentsSelected) {
+ const allAgentsOptions = find(['label', ALL_AGENTS_LABEL], options);
+
+ if (allAgentsOptions?.options) {
+ setSelectedOptions(allAgentsOptions.options);
+ defaultValueInitialized.current = true;
+ }
+ }
+
+ if (agentSelection.policiesSelected.length) {
+ const policyOptions = find(['label', AGENT_POLICY_LABEL], options);
if (policyOptions) {
const defaultOptions = policyOptions.options?.filter((option) =>
@@ -82,12 +96,12 @@ const AgentsTableComponent: React.FC = ({ agentSelection, onCh
if (defaultOptions?.length) {
setSelectedOptions(defaultOptions);
+ defaultValueInitialized.current = true;
}
- defaultValueInitialized.current = true;
}
}
}
- }, [agentSelection, options]);
+ }, [agentSelection, options, selectedOptions]);
useEffect(() => {
// update the groups when groups or agents have changed
diff --git a/x-pack/plugins/osquery/public/agents/use_agent_details.ts b/x-pack/plugins/osquery/public/agents/use_agent_details.ts
new file mode 100644
index 00000000000000..1a0663812dec36
--- /dev/null
+++ b/x-pack/plugins/osquery/public/agents/use_agent_details.ts
@@ -0,0 +1,36 @@
+/*
+ * 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 { i18n } from '@kbn/i18n';
+import { useQuery } from 'react-query';
+
+import { GetOneAgentResponse, agentRouteService } from '../../../fleet/common';
+import { useErrorToast } from '../common/hooks/use_error_toast';
+import { useKibana } from '../common/lib/kibana';
+
+interface UseAgentDetails {
+ agentId: string;
+}
+
+export const useAgentDetails = ({ agentId }: UseAgentDetails) => {
+ const { http } = useKibana().services;
+ const setErrorToast = useErrorToast();
+ return useQuery(
+ ['agentDetails', agentId],
+ () => http.get(agentRouteService.getInfoPath(agentId)),
+ {
+ enabled: agentId.length > 0,
+ onSuccess: () => setErrorToast(),
+ onError: (error) =>
+ setErrorToast(error as Error, {
+ title: i18n.translate('xpack.osquery.agentDetails.fetchError', {
+ defaultMessage: 'Error while fetching agent details',
+ }),
+ }),
+ }
+ );
+};
diff --git a/x-pack/plugins/osquery/public/agents/use_all_agents.ts b/x-pack/plugins/osquery/public/agents/use_all_agents.ts
index 30ba4d2f579079..cda15cc8054371 100644
--- a/x-pack/plugins/osquery/public/agents/use_all_agents.ts
+++ b/x-pack/plugins/osquery/public/agents/use_all_agents.ts
@@ -38,7 +38,7 @@ export const useAllAgents = (
let kuery = `last_checkin_status: online and (${policyFragment})`;
if (searchValue) {
- kuery += `and (local_metadata.host.hostname:*${searchValue}* or local_metadata.elastic.agent.id:*${searchValue}*)`;
+ kuery += ` and (local_metadata.host.hostname:*${searchValue}* or local_metadata.elastic.agent.id:*${searchValue}*)`;
}
return http.get(agentRouteService.getListPath(), {
diff --git a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx
index 9f0b5acd8994a5..070339bb58af22 100644
--- a/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx
+++ b/x-pack/plugins/osquery/public/live_queries/form/live_query_query_field.tsx
@@ -6,12 +6,15 @@
*/
import { EuiFormRow, EuiSpacer } from '@elastic/eui';
-import React, { useCallback } from 'react';
+import React, { useCallback, useRef } from 'react';
import { OsquerySchemaLink } from '../../components/osquery_schema_link';
import { FieldHook } from '../../shared_imports';
import { OsqueryEditor } from '../../editor';
-import { SavedQueriesDropdown } from '../../saved_queries/saved_queries_dropdown';
+import {
+ SavedQueriesDropdown,
+ SavedQueriesDropdownRef,
+} from '../../saved_queries/saved_queries_dropdown';
interface LiveQueryQueryFieldProps {
disabled?: boolean;
@@ -21,16 +24,18 @@ interface LiveQueryQueryFieldProps {
const LiveQueryQueryFieldComponent: React.FC = ({ disabled, field }) => {
const { value, setValue, errors } = field;
const error = errors[0]?.message;
+ const savedQueriesDropdownRef = useRef(null);
const handleSavedQueryChange = useCallback(
(savedQuery) => {
- setValue(savedQuery.query);
+ setValue(savedQuery?.query ?? '');
},
[setValue]
);
const handleEditorChange = useCallback(
(newValue) => {
+ savedQueriesDropdownRef.current?.clearSelection();
setValue(newValue);
},
[setValue]
@@ -39,7 +44,11 @@ const LiveQueryQueryFieldComponent: React.FC = ({ disa
return (
<>
-
+
}>
diff --git a/x-pack/plugins/osquery/public/routes/live_queries/new/index.tsx b/x-pack/plugins/osquery/public/routes/live_queries/new/index.tsx
index 9967eb97cddf22..40614c1f3e1b8e 100644
--- a/x-pack/plugins/osquery/public/routes/live_queries/new/index.tsx
+++ b/x-pack/plugins/osquery/public/routes/live_queries/new/index.tsx
@@ -8,7 +8,7 @@
import { EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { useMemo } from 'react';
-import { useLocation } from 'react-router-dom';
+import { useHistory, useLocation } from 'react-router-dom';
import qs from 'query-string';
import { WithHeaderLayout } from '../../../components/layouts';
@@ -19,12 +19,18 @@ import { BetaBadge, BetaBadgeRowWrapper } from '../../../components/beta_badge';
const NewLiveQueryPageComponent = () => {
useBreadcrumbs('live_query_new');
+ const { replace } = useHistory();
const location = useLocation();
const liveQueryListProps = useRouterNavigate('live_queries');
const formDefaultValue = useMemo(() => {
const queryParams = qs.parse(location.search);
+ if (location.state?.form.query) {
+ replace({ state: null });
+ return { query: location.state?.form.query };
+ }
+
if (queryParams?.agentPolicyId) {
return {
agentSelection: {
@@ -37,7 +43,7 @@ const NewLiveQueryPageComponent = () => {
}
return undefined;
- }, [location.search]);
+ }, [location.search, location.state, replace]);
const LeftColumn = useMemo(
() => (
diff --git a/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx b/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx
index 7e8e8e543dfabf..8738c06d065979 100644
--- a/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx
+++ b/x-pack/plugins/osquery/public/routes/saved_queries/list/index.tsx
@@ -16,6 +16,7 @@ import {
import React, { useCallback, useMemo, useState } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import { useHistory } from 'react-router-dom';
import { SavedObject } from 'kibana/public';
import { WithHeaderLayout } from '../../../components/layouts';
@@ -51,6 +52,7 @@ const EditButton = React.memo(EditButtonComponent);
const SavedQueriesPageComponent = () => {
useBreadcrumbs('saved_queries');
+ const { push } = useHistory();
const newQueryLinkProps = useRouterNavigate('saved_queries/new');
const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(10);
@@ -59,21 +61,15 @@ const SavedQueriesPageComponent = () => {
const { data } = useSavedQueries({ isLive: true });
- // const handlePlayClick = useCallback(
- // (item) =>
- // push({
- // search: qs.stringify({
- // tab: 'live_query',
- // }),
- // state: {
- // query: {
- // id: item.id,
- // query: item.attributes.query,
- // },
- // },
- // }),
- // [push]
- // );
+ const handlePlayClick = useCallback(
+ (item) =>
+ push('/live_queries/new', {
+ form: {
+ savedQueryId: item.id,
+ },
+ }),
+ [push]
+ );
const renderEditAction = useCallback(
(item: SavedObject<{ name: string }>) => (
@@ -96,45 +92,53 @@ const SavedQueriesPageComponent = () => {
() => [
{
field: 'attributes.id',
- name: 'Query ID',
+ name: i18n.translate('xpack.osquery.savedQueries.table.queryIdColumnTitle', {
+ defaultMessage: 'Query ID',
+ }),
sortable: true,
truncateText: true,
},
{
field: 'attributes.description',
- name: 'Description',
+ name: i18n.translate('xpack.osquery.savedQueries.table.descriptionColumnTitle', {
+ defaultMessage: 'Description',
+ }),
sortable: true,
truncateText: true,
},
{
field: 'attributes.created_by',
- name: 'Created by',
+ name: i18n.translate('xpack.osquery.savedQueries.table.createdByColumnTitle', {
+ defaultMessage: 'Created by',
+ }),
sortable: true,
truncateText: true,
},
{
field: 'attributes.updated_at',
- name: 'Last updated at',
+ name: i18n.translate('xpack.osquery.savedQueries.table.updatedAtColumnTitle', {
+ defaultMessage: 'Last updated at',
+ }),
sortable: (item: SavedObject<{ updated_at: string }>) =>
item.attributes.updated_at ? Date.parse(item.attributes.updated_at) : 0,
truncateText: true,
render: renderUpdatedAt,
},
{
- name: 'Actions',
+ name: i18n.translate('xpack.osquery.savedQueries.table.actionsColumnTitle', {
+ defaultMessage: 'Actions',
+ }),
actions: [
- // {
- // name: 'Live query',
- // description: 'Run live query',
- // type: 'icon',
- // icon: 'play',
- // onClick: handlePlayClick,
- // },
+ {
+ type: 'icon',
+ icon: 'play',
+ onClick: handlePlayClick,
+ },
{ render: renderEditAction },
],
},
],
- [renderEditAction, renderUpdatedAt]
+ [handlePlayClick, renderEditAction, renderUpdatedAt]
);
const onTableChange = useCallback(({ page = {}, sort = {} }) => {
diff --git a/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx b/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx
index e30954a695b2d9..30df2267fbfa16 100644
--- a/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx
+++ b/x-pack/plugins/osquery/public/saved_queries/saved_queries_dropdown.tsx
@@ -7,44 +7,70 @@
import { find } from 'lodash/fp';
import { EuiCodeBlock, EuiFormRow, EuiComboBox, EuiText } from '@elastic/eui';
-import React, { useCallback, useState } from 'react';
+import React, {
+ forwardRef,
+ useCallback,
+ useEffect,
+ useImperativeHandle,
+ useMemo,
+ useState,
+} from 'react';
import { SimpleSavedObject } from 'kibana/public';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
+import { useHistory, useLocation } from 'react-router-dom';
import { useSavedQueries } from './use_saved_queries';
+export interface SavedQueriesDropdownRef {
+ clearSelection: () => void;
+}
+
interface SavedQueriesDropdownProps {
disabled?: boolean;
onChange: (
- value: SimpleSavedObject<{
- id: string;
- description?: string | undefined;
- query: string;
- }>['attributes']
+ value:
+ | SimpleSavedObject<{
+ id: string;
+ description?: string | undefined;
+ query: string;
+ }>['attributes']
+ | null
) => void;
}
-const SavedQueriesDropdownComponent: React.FC = ({
- disabled,
- onChange,
-}) => {
+const SavedQueriesDropdownComponent = forwardRef<
+ SavedQueriesDropdownRef,
+ SavedQueriesDropdownProps
+>(({ disabled, onChange }, ref) => {
+ const { replace } = useHistory();
+ const location = useLocation();
const [selectedOptions, setSelectedOptions] = useState([]);
const { data } = useSavedQueries({});
- const queryOptions =
- data?.savedObjects?.map((savedQuery) => ({
- label: savedQuery.attributes.id ?? '',
- value: {
- id: savedQuery.attributes.id,
- description: savedQuery.attributes.description,
- query: savedQuery.attributes.query,
- },
- })) ?? [];
+ const queryOptions = useMemo(
+ () =>
+ data?.savedObjects?.map((savedQuery) => ({
+ label: savedQuery.attributes.id ?? '',
+ value: {
+ savedObjectId: savedQuery.id,
+ id: savedQuery.attributes.id,
+ description: savedQuery.attributes.description,
+ query: savedQuery.attributes.query,
+ },
+ })) ?? [],
+ [data?.savedObjects]
+ );
const handleSavedQueryChange = useCallback(
(newSelectedOptions) => {
+ if (!newSelectedOptions.length) {
+ onChange(null);
+ setSelectedOptions(newSelectedOptions);
+ return;
+ }
+
const selectedSavedQuery = find(
['attributes.id', newSelectedOptions[0].value.id],
data?.savedObjects
@@ -73,6 +99,30 @@ const SavedQueriesDropdownComponent: React.FC = ({
[]
);
+ const clearSelection = useCallback(() => setSelectedOptions([]), []);
+
+ useEffect(() => {
+ const savedQueryId = location.state?.form?.savedQueryId;
+
+ if (savedQueryId) {
+ const savedQueryOption = find(['value.savedObjectId', savedQueryId], queryOptions);
+
+ if (savedQueryOption) {
+ handleSavedQueryChange([savedQueryOption]);
+ }
+
+ replace({ state: null });
+ }
+ }, [handleSavedQueryChange, replace, location.state, queryOptions]);
+
+ useImperativeHandle(
+ ref,
+ () => ({
+ clearSelection,
+ }),
+ [clearSelection]
+ );
+
return (
= ({
/>
);
-};
+});
export const SavedQueriesDropdown = React.memo(SavedQueriesDropdownComponent);
diff --git a/x-pack/plugins/osquery/public/scheduled_query_groups/queries/query_flyout.tsx b/x-pack/plugins/osquery/public/scheduled_query_groups/queries/query_flyout.tsx
index 32547bc5dd2d08..95a31efeaf135b 100644
--- a/x-pack/plugins/osquery/public/scheduled_query_groups/queries/query_flyout.tsx
+++ b/x-pack/plugins/osquery/public/scheduled_query_groups/queries/query_flyout.tsx
@@ -71,10 +71,14 @@ const QueryFlyoutComponent: React.FC = ({
[integrationPackageVersion]
);
- const { submit, setFieldValue } = form;
+ const { submit, setFieldValue, reset } = form;
const handleSetQueryValue = useCallback(
(savedQuery) => {
+ if (!savedQuery) {
+ return reset();
+ }
+
setFieldValue('id', savedQuery.id);
setFieldValue('query', savedQuery.query);
@@ -94,7 +98,7 @@ const QueryFlyoutComponent: React.FC = ({
setFieldValue('version', [savedQuery.version]);
}
},
- [isFieldSupported, setFieldValue]
+ [isFieldSupported, setFieldValue, reset]
);
return (
diff --git a/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_table.tsx b/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_table.tsx
index 36d15587086f2d..01acf2dc0d8263 100644
--- a/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_table.tsx
+++ b/x-pack/plugins/osquery/public/scheduled_query_groups/scheduled_query_group_queries_table.tsx
@@ -258,7 +258,7 @@ const ViewResultsInDiscoverActionComponent: React.FC;
}>;
}>;
+ // disabling naming-convention to accommodate external field
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ Memory_protection: Partial<{
+ feature: ECSField;
+ self_injection: ECSField;
+ }>;
+ Target: Partial<{
+ process: Partial<{
+ thread: Partial<{
+ Ext: Partial<{
+ start_address_allocation_offset: ECSField;
+ start_address_bytes_disasm_hash: ECSField;
+ start_address_details: Partial<{
+ allocation_type: ECSField;
+ allocation_size: ECSField;
+ region_size: ECSField;
+ region_protection: ECSField;
+ memory_pe: Partial<{
+ imphash: ECSField;
+ }>;
+ }>;
+ }>;
+ }>;
+ }>;
+ }>;
process: Partial<{
command_line: ECSField;
ppid: ECSField;
@@ -328,6 +353,10 @@ export type AlertEvent = Partial<{
>;
}>;
user: ECSField;
+ malware_signature: Partial<{
+ all_names: ECSField;
+ identifier: ECSField;
+ }>;
}>;
}>;
file: Partial<{
@@ -400,6 +429,11 @@ export enum HostStatus {
* Host is inactive as indicated by its checkin status during the last checkin window
*/
INACTIVE = 'inactive',
+
+ /**
+ * Host is unenrolled
+ */
+ UNENROLLED = 'unenrolled',
}
export type PolicyInfo = Immutable<{
diff --git a/x-pack/plugins/security_solution/cypress/ccs_integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/ccs_integration/detection_alerts/alerts_details.spec.ts
index f87399a6669048..229bbcce87696d 100644
--- a/x-pack/plugins/security_solution/cypress/ccs_integration/detection_alerts/alerts_details.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/ccs_integration/detection_alerts/alerts_details.spec.ts
@@ -18,7 +18,7 @@ import { cleanKibana } from '../../tasks/common';
import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import { esArchiverCCSLoad, esArchiverCCSUnload } from '../../tasks/es_archiver';
-import { unmappedCCSRule } from '../../objects/rule';
+import { getUnmappedCCSRule } from '../../objects/rule';
import { ALERTS_URL } from '../../urls/navigation';
@@ -29,7 +29,7 @@ describe('Alert details with unmapped fields', () => {
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(unmappedCCSRule);
+ createCustomRuleActivated(getUnmappedCCSRule());
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
expandFirstAlert();
diff --git a/x-pack/plugins/security_solution/cypress/integration/cases/attach_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/integration/cases/attach_timeline.spec.ts
index 29105ce1582cf0..e94f7d00f0b378 100644
--- a/x-pack/plugins/security_solution/cypress/integration/cases/attach_timeline.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/cases/attach_timeline.spec.ts
@@ -13,8 +13,8 @@ import {
selectCase,
} from '../../tasks/timeline';
import { DESCRIPTION_INPUT, ADD_COMMENT_INPUT } from '../../screens/create_new_case';
-import { case1 } from '../../objects/case';
-import { timeline } from '../../objects/timeline';
+import { getCase1 } from '../../objects/case';
+import { getTimeline } from '../../objects/timeline';
import { createTimeline } from '../../tasks/api_calls/timelines';
import { cleanKibana } from '../../tasks/common';
import { createCase } from '../../tasks/api_calls/cases';
@@ -23,7 +23,7 @@ describe('attach timeline to case', () => {
context('without cases created', () => {
beforeEach(() => {
cleanKibana();
- createTimeline(timeline).then((response) => {
+ createTimeline(getTimeline()).then((response) => {
cy.wrap(response.body.data.persistTimeline.timeline).as('myTimeline');
});
});
@@ -57,10 +57,10 @@ describe('attach timeline to case', () => {
context('with cases created', () => {
before(() => {
cleanKibana();
- createTimeline(timeline).then((response) =>
+ createTimeline(getTimeline()).then((response) =>
cy.wrap(response.body.data.persistTimeline.timeline.savedObjectId).as('timelineId')
);
- createCase(case1).then((response) => cy.wrap(response.body.id).as('caseId'));
+ createCase(getCase1()).then((response) => cy.wrap(response.body.id).as('caseId'));
});
it('attach timeline to an existing case', function () {
@@ -71,7 +71,9 @@ describe('attach timeline to case', () => {
cy.location('origin').then((origin) => {
cy.get(ADD_COMMENT_INPUT).should(
'have.text',
- `[${timeline.title}](${origin}/app/security/timelines?timeline=(id:%27${this.timelineId}%27,isOpen:!t))`
+ `[${getTimeline().title}](${origin}/app/security/timelines?timeline=(id:%27${
+ this.timelineId
+ }%27,isOpen:!t))`
);
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/cases/connector_options.spec.ts b/x-pack/plugins/security_solution/cypress/integration/cases/connector_options.spec.ts
index 95b555c2acae6d..0959f999a4b53c 100644
--- a/x-pack/plugins/security_solution/cypress/integration/cases/connector_options.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/cases/connector_options.spec.ts
@@ -7,13 +7,13 @@
import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import {
- case1,
- connectorIds,
- mockConnectorsResponse,
- executeResponses,
- ibmResilientConnectorOptions,
- jiraConnectorOptions,
- serviceNowConnectorOpions,
+ getCase1,
+ getConnectorIds,
+ getMockConnectorsResponse,
+ getExecuteResponses,
+ getIbmResilientConnectorOptions,
+ getJiraConnectorOptions,
+ getServiceNowConnectorOptions,
} from '../../objects/case';
import {
createCase,
@@ -30,26 +30,26 @@ import { cleanKibana } from '../../tasks/common';
describe('Cases connector incident fields', () => {
beforeEach(() => {
cleanKibana();
- cy.intercept('GET', '/api/cases/configure/connectors/_find', mockConnectorsResponse);
- cy.intercept('POST', `/api/actions/action/${connectorIds.sn}/_execute`, (req) => {
+ cy.intercept('GET', '/api/cases/configure/connectors/_find', getMockConnectorsResponse());
+ cy.intercept('POST', `/api/actions/action/${getConnectorIds().sn}/_execute`, (req) => {
const response =
req.body.params.subAction === 'getChoices'
- ? executeResponses.servicenow.choices
+ ? getExecuteResponses().servicenow.choices
: { status: 'ok', data: [] };
req.reply(response);
});
- cy.intercept('POST', `/api/actions/action/${connectorIds.jira}/_execute`, (req) => {
+ cy.intercept('POST', `/api/actions/action/${getConnectorIds().jira}/_execute`, (req) => {
const response =
req.body.params.subAction === 'issueTypes'
- ? executeResponses.jira.issueTypes
- : executeResponses.jira.fieldsByIssueType;
+ ? getExecuteResponses().jira.issueTypes
+ : getExecuteResponses().jira.fieldsByIssueType;
req.reply(response);
});
- cy.intercept('POST', `/api/actions/action/${connectorIds.resilient}/_execute`, (req) => {
+ cy.intercept('POST', `/api/actions/action/${getConnectorIds().resilient}/_execute`, (req) => {
const response =
req.body.params.subAction === 'incidentTypes'
- ? executeResponses.resilient.incidentTypes
- : executeResponses.resilient.severity;
+ ? getExecuteResponses().resilient.incidentTypes
+ : getExecuteResponses().resilient.severity;
req.reply(response);
});
});
@@ -57,19 +57,19 @@ describe('Cases connector incident fields', () => {
it('Correct incident fields show when connector is changed', () => {
loginAndWaitForPageWithoutDateRange(CASES_URL);
goToCreateNewCase();
- fillCasesMandatoryfields(case1);
- fillJiraConnectorOptions(jiraConnectorOptions);
- fillServiceNowConnectorOptions(serviceNowConnectorOpions);
- fillIbmResilientConnectorOptions(ibmResilientConnectorOptions);
+ fillCasesMandatoryfields(getCase1());
+ fillJiraConnectorOptions(getJiraConnectorOptions());
+ fillServiceNowConnectorOptions(getServiceNowConnectorOptions());
+ fillIbmResilientConnectorOptions(getIbmResilientConnectorOptions());
createCase();
- cy.get(CONNECTOR_TITLE).should('have.text', ibmResilientConnectorOptions.title);
+ cy.get(CONNECTOR_TITLE).should('have.text', getIbmResilientConnectorOptions().title);
cy.get(CONNECTOR_CARD_DETAILS).should(
'have.text',
`${
- ibmResilientConnectorOptions.title
- }Incident Types: ${ibmResilientConnectorOptions.incidentTypes.join(', ')}Severity: ${
- ibmResilientConnectorOptions.severity
+ getIbmResilientConnectorOptions().title
+ }Incident Types: ${getIbmResilientConnectorOptions().incidentTypes.join(', ')}Severity: ${
+ getIbmResilientConnectorOptions().severity
}`
);
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/cases/connectors.spec.ts b/x-pack/plugins/security_solution/cypress/integration/cases/connectors.spec.ts
index 9e55067ce4ed4d..aa1bd7a5db5cc0 100644
--- a/x-pack/plugins/security_solution/cypress/integration/cases/connectors.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/cases/connectors.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { serviceNowConnector } from '../../objects/case';
+import { getServiceNowConnector } from '../../objects/case';
import { SERVICE_NOW_MAPPING, TOASTER } from '../../screens/configure_cases';
@@ -77,7 +77,7 @@ describe('Cases connectors', () => {
loginAndWaitForPageWithoutDateRange(CASES_URL);
goToEditExternalConnection();
openAddNewConnectorOption();
- addServiceNowConnector(serviceNowConnector);
+ addServiceNowConnector(getServiceNowConnector());
cy.wait('@createConnector').then(({ response }) => {
cy.wrap(response!.statusCode).should('eql', 200);
diff --git a/x-pack/plugins/security_solution/cypress/integration/cases/creation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/cases/creation.spec.ts
index c568aaae664a09..9e3b775156cabd 100644
--- a/x-pack/plugins/security_solution/cypress/integration/cases/creation.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/cases/creation.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { case1 } from '../../objects/case';
+import { getCase1, TestCase } from '../../objects/case';
import {
ALL_CASES_CLOSED_CASES_STATS,
@@ -55,12 +55,12 @@ import { CASES_URL } from '../../urls/navigation';
describe('Cases', () => {
beforeEach(() => {
cleanKibana();
- createTimeline(case1.timeline).then((response) =>
+ createTimeline(getCase1().timeline).then((response) =>
cy
.wrap({
- ...case1,
+ ...getCase1(),
timeline: {
- ...case1.timeline,
+ ...getCase1().timeline,
id: response.body.data.persistTimeline.timeline.savedObjectId,
},
})
@@ -86,7 +86,7 @@ describe('Cases', () => {
cy.get(ALL_CASES_TAGS_COUNT).should('have.text', 'Tags2');
cy.get(ALL_CASES_NAME).should('have.text', this.mycase.name);
cy.get(ALL_CASES_REPORTER).should('have.text', this.mycase.reporter);
- (this.mycase as typeof case1).tags.forEach((tag, index) => {
+ (this.mycase as TestCase).tags.forEach((tag, index) => {
cy.get(ALL_CASES_TAGS(index)).should('have.text', tag);
});
cy.get(ALL_CASES_COMMENTS_COUNT).should('have.text', '0');
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
index d9ca43339d4126..825cc7f8081e5f 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_details.spec.ts
@@ -18,7 +18,7 @@ import { cleanKibana } from '../../tasks/common';
import { esArchiverLoad } from '../../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
-import { unmappedRule } from '../../objects/rule';
+import { getUnmappedRule } from '../../objects/rule';
import { ALERTS_URL } from '../../urls/navigation';
@@ -29,7 +29,7 @@ describe('Alert details with unmapped fields', () => {
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(unmappedRule);
+ createCustomRuleActivated(getUnmappedRule());
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
expandFirstAlert();
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts
index fb0b96c977e32c..eaed80c484f603 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/alerts_detection_callouts_index_outdated.spec.ts
@@ -7,7 +7,7 @@
import { ROLES } from '../../../common/test';
import { DETECTIONS_RULE_MANAGEMENT_URL, ALERTS_URL } from '../../urls/navigation';
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import { PAGE_TITLE } from '../../screens/common/page';
import {
@@ -77,7 +77,7 @@ describe('Detections > Need Admin Callouts indicating an admin is needed to migr
context('On Rule Details page', () => {
beforeEach(() => {
- createCustomRule(newRule);
+ createCustomRule(getNewRule());
loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
waitForPageTitleToBeShown();
goToRuleDetails();
@@ -127,7 +127,7 @@ describe('Detections > Need Admin Callouts indicating an admin is needed to migr
context('On Rule Details page', () => {
beforeEach(() => {
- createCustomRule(newRule);
+ createCustomRule(getNewRule());
loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
waitForPageTitleToBeShown();
goToRuleDetails();
@@ -177,7 +177,7 @@ describe('Detections > Need Admin Callouts indicating an admin is needed to migr
context('On Rule Details page', () => {
beforeEach(() => {
- createCustomRule(newRule);
+ createCustomRule(getNewRule());
loadPageAsPlatformEngineerUser(DETECTIONS_RULE_MANAGEMENT_URL);
waitForPageTitleToBeShown();
goToRuleDetails();
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/attach_to_case.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/attach_to_case.spec.ts
index 6cc5d2443e7840..e052d1a3272acc 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/attach_to_case.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/attach_to_case.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import { ROLES } from '../../../common/test';
import { waitForAlertsIndexToBeCreated, waitForAlertsPanelToBeLoaded } from '../../tasks/alerts';
@@ -30,7 +30,7 @@ describe('Alerts timeline', () => {
loginAndWaitForPage(ALERTS_URL, ROLES.platform_engineer);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(newRule);
+ createCustomRuleActivated(getNewRule());
refreshPage();
waitForAlertsToPopulate(500);
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/closing.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/closing.spec.ts
index 6ae23733d6434b..038bc30c90c1e0 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/closing.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/closing.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import {
ALERTS,
ALERTS_COUNT,
@@ -39,7 +39,7 @@ describe('Closing alerts', () => {
loginAndWaitForPage(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(newRule, '1', '100m', 100);
+ createCustomRuleActivated(getNewRule(), '1', '100m', 100);
refreshPage();
waitForAlertsToPopulate(100);
deleteCustomRule();
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/cti_enrichments.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/cti_enrichments.spec.ts
index b03daf74ce247a..522e25590994fe 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/cti_enrichments.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/cti_enrichments.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { newThreatIndicatorRule } from '../../objects/rule';
+import { getNewThreatIndicatorRule } from '../../objects/rule';
import { cleanKibana, reload } from '../../tasks/common';
import { esArchiverLoad, esArchiverUnload } from '../../tasks/es_archiver';
import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
@@ -39,7 +39,7 @@ describe('CTI Enrichment', () => {
esArchiverLoad('suspicious_source_event');
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
goToManageAlertsDetectionRules();
- createCustomIndicatorRule(newThreatIndicatorRule);
+ createCustomIndicatorRule(getNewThreatIndicatorRule());
reload();
});
@@ -56,9 +56,9 @@ describe('CTI Enrichment', () => {
it('Displays enrichment matched.* fields on the timeline', () => {
const expectedFields = {
- 'threat.indicator.matched.atomic': newThreatIndicatorRule.atomic,
+ 'threat.indicator.matched.atomic': getNewThreatIndicatorRule().atomic,
'threat.indicator.matched.type': 'indicator_match_rule',
- 'threat.indicator.matched.field': newThreatIndicatorRule.indicatorMappingField,
+ 'threat.indicator.matched.field': getNewThreatIndicatorRule().indicatorMappingField,
};
const fields = Object.keys(expectedFields) as Array;
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/in_progress.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/in_progress.spec.ts
index cb8694d5c35af2..890f8a064aa9e4 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/in_progress.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/in_progress.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import {
ALERTS,
ALERTS_COUNT,
@@ -36,7 +36,7 @@ describe('Marking alerts as in-progress', () => {
loginAndWaitForPage(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(newRule);
+ createCustomRuleActivated(getNewRule());
refreshPage();
waitForAlertsToPopulate(500);
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/investigate_in_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/investigate_in_timeline.spec.ts
index 115118b6762d9d..01a06b3d592666 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/investigate_in_timeline.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/investigate_in_timeline.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import { PROVIDER_BADGE } from '../../screens/timeline';
import {
@@ -27,7 +27,7 @@ describe('Alerts timeline', () => {
loginAndWaitForPage(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(newRule);
+ createCustomRuleActivated(getNewRule());
refreshPage();
waitForAlertsToPopulate(500);
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/missing_privileges_callout.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/missing_privileges_callout.spec.ts
index 20a863e742efd6..0db30179284e08 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/missing_privileges_callout.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/missing_privileges_callout.spec.ts
@@ -7,7 +7,7 @@
import { ROLES } from '../../../common/test';
import { DETECTIONS_RULE_MANAGEMENT_URL, ALERTS_URL } from '../../urls/navigation';
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import { PAGE_TITLE } from '../../screens/common/page';
import {
@@ -95,7 +95,7 @@ describe('Detections > Callouts', () => {
context('On Rule Details page', () => {
beforeEach(() => {
- createCustomRule(newRule);
+ createCustomRule(getNewRule());
loadPageAsReadOnlyUser(DETECTIONS_RULE_MANAGEMENT_URL);
waitForPageTitleToBeShown();
goToRuleDetails();
@@ -145,7 +145,7 @@ describe('Detections > Callouts', () => {
context('On Rule Details page', () => {
beforeEach(() => {
- createCustomRule(newRule);
+ createCustomRule(getNewRule());
loadPageAsPlatformEngineer(DETECTIONS_RULE_MANAGEMENT_URL);
waitForPageTitleToBeShown();
goToRuleDetails();
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/opening.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/opening.spec.ts
index 6cbc82b93f446f..4f78bdac847892 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_alerts/opening.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_alerts/opening.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import {
ALERTS_COUNT,
SELECTED_ALERTS,
@@ -37,7 +37,7 @@ describe('Opening alerts', () => {
loginAndWaitForPage(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(newRule);
+ createCustomRuleActivated(getNewRule());
refreshPage();
waitForAlertsToPopulate(500);
selectNumberOfAlerts(5);
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts
index 218b1f7745d947..e30cde49892845 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts
@@ -7,11 +7,11 @@
import { formatMitreAttackDescription } from '../../helpers/rules';
import {
- newRule,
- existingRule,
- indexPatterns,
- editedRule,
- newOverrideRule,
+ getNewRule,
+ getExistingRule,
+ getIndexPatterns,
+ getEditedRule,
+ getNewOverrideRule,
} from '../../objects/rule';
import {
ALERT_RULE_METHOD,
@@ -120,19 +120,19 @@ import { activatesRule } from '../../tasks/rule_details';
import { ALERTS_URL } from '../../urls/navigation';
describe('Custom detection rules creation', () => {
- const expectedUrls = newRule.referenceUrls.join('');
- const expectedFalsePositives = newRule.falsePositivesExamples.join('');
- const expectedTags = newRule.tags.join('');
- const expectedMitre = formatMitreAttackDescription(newRule.mitre);
+ const expectedUrls = getNewRule().referenceUrls.join('');
+ const expectedFalsePositives = getNewRule().falsePositivesExamples.join('');
+ const expectedTags = getNewRule().tags.join('');
+ const expectedMitre = formatMitreAttackDescription(getNewRule().mitre);
const expectedNumberOfRules = 1;
beforeEach(() => {
cleanKibana();
- createTimeline(newRule.timeline).then((response) => {
+ createTimeline(getNewRule().timeline).then((response) => {
cy.wrap({
- ...newRule,
+ ...getNewRule(),
timeline: {
- ...newRule.timeline,
+ ...getNewRule().timeline,
id: response.body.data.persistTimeline.timeline.savedObjectId,
},
}).as('rule');
@@ -201,7 +201,7 @@ describe('Custom detection rules creation', () => {
cy.get(INVESTIGATION_NOTES_TOGGLE).click({ force: true });
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
- getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join(''));
+ getDetails(INDEX_PATTERNS_DETAILS).should('have.text', getIndexPatterns().join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', this.rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
@@ -209,11 +209,11 @@ describe('Custom detection rules creation', () => {
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should(
'have.text',
- `${newRule.runsEvery.interval}${newRule.runsEvery.type}`
+ `${getNewRule().runsEvery.interval}${getNewRule().runsEvery.type}`
);
getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should(
'have.text',
- `${newRule.lookBack.interval}${newRule.lookBack.type}`
+ `${getNewRule().lookBack.interval}${getNewRule().lookBack.type}`
);
});
@@ -236,9 +236,9 @@ describe('Custom detection rules deletion and edition', () => {
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
goToManageAlertsDetectionRules();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(newRule, 'rule1');
- createCustomRuleActivated(newOverrideRule, 'rule2');
- createCustomRuleActivated(existingRule, 'rule3');
+ createCustomRuleActivated(getNewRule(), 'rule1');
+ createCustomRuleActivated(getNewOverrideRule(), 'rule2');
+ createCustomRuleActivated(getExistingRule(), 'rule3');
reload();
});
@@ -303,16 +303,18 @@ describe('Custom detection rules deletion and edition', () => {
});
context('Edition', () => {
- const expectedEditedtags = editedRule.tags.join('');
+ const expectedEditedtags = getEditedRule().tags.join('');
const expectedEditedIndexPatterns =
- editedRule.index && editedRule.index.length ? editedRule.index : indexPatterns;
+ getEditedRule().index && getEditedRule().index.length
+ ? getEditedRule().index
+ : getIndexPatterns();
beforeEach(() => {
cleanKibana();
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
goToManageAlertsDetectionRules();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(existingRule, 'rule1');
+ createCustomRuleActivated(getExistingRule(), 'rule1');
reload();
});
@@ -326,7 +328,7 @@ describe('Custom detection rules deletion and edition', () => {
cy.wait('@fetchRuleDetails').then(({ response }) => {
cy.wrap(response!.statusCode).should('eql', 200);
- cy.wrap(response!.body.max_signals).should('eql', existingRule.maxSignals);
+ cy.wrap(response!.body.max_signals).should('eql', getExistingRule().maxSignals);
cy.wrap(response!.body.enabled).should('eql', false);
});
});
@@ -336,25 +338,25 @@ describe('Custom detection rules deletion and edition', () => {
waitForKibana();
// expect define step to populate
- cy.get(CUSTOM_QUERY_INPUT).should('have.value', existingRule.customQuery);
- if (existingRule.index && existingRule.index.length > 0) {
- cy.get(DEFINE_INDEX_INPUT).should('have.text', existingRule.index.join(''));
+ cy.get(CUSTOM_QUERY_INPUT).should('have.value', getExistingRule().customQuery);
+ if (getExistingRule().index && getExistingRule().index.length > 0) {
+ cy.get(DEFINE_INDEX_INPUT).should('have.text', getExistingRule().index.join(''));
}
goToAboutStepTab();
// expect about step to populate
- cy.get(RULE_NAME_INPUT).invoke('val').should('eql', existingRule.name);
- cy.get(RULE_DESCRIPTION_INPUT).should('have.text', existingRule.description);
- cy.get(TAGS_FIELD).should('have.text', existingRule.tags.join(''));
- cy.get(SEVERITY_DROPDOWN).should('have.text', existingRule.severity);
- cy.get(DEFAULT_RISK_SCORE_INPUT).invoke('val').should('eql', existingRule.riskScore);
+ cy.get(RULE_NAME_INPUT).invoke('val').should('eql', getExistingRule().name);
+ cy.get(RULE_DESCRIPTION_INPUT).should('have.text', getExistingRule().description);
+ cy.get(TAGS_FIELD).should('have.text', getExistingRule().tags.join(''));
+ cy.get(SEVERITY_DROPDOWN).should('have.text', getExistingRule().severity);
+ cy.get(DEFAULT_RISK_SCORE_INPUT).invoke('val').should('eql', getExistingRule().riskScore);
goToScheduleStepTab();
// expect schedule step to populate
- const intervalParts =
- existingRule.interval && existingRule.interval.match(/[0-9]+|[a-zA-Z]+/g);
+ const interval = getExistingRule().interval;
+ const intervalParts = interval != null && interval.match(/[0-9]+|[a-zA-Z]+/g);
if (intervalParts) {
const [amount, unit] = intervalParts;
cy.get(SCHEDULE_INTERVAL_AMOUNT_INPUT).invoke('val').should('eql', amount);
@@ -380,7 +382,7 @@ describe('Custom detection rules deletion and edition', () => {
goToAboutStepTab();
cy.get(TAGS_CLEAR_BUTTON).click({ force: true });
- fillAboutRule(editedRule);
+ fillAboutRule(getEditedRule());
cy.intercept('GET', '/api/detection_engine/rules?id').as('getRule');
@@ -389,30 +391,30 @@ describe('Custom detection rules deletion and edition', () => {
cy.wait('@getRule').then(({ response }) => {
cy.wrap(response!.statusCode).should('eql', 200);
// ensure that editing rule does not modify max_signals
- cy.wrap(response!.body.max_signals).should('eql', existingRule.maxSignals);
+ cy.wrap(response!.body.max_signals).should('eql', getExistingRule().maxSignals);
});
- cy.get(RULE_NAME_HEADER).should('contain', `${editedRule.name}`);
- cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', editedRule.description);
+ cy.get(RULE_NAME_HEADER).should('contain', `${getEditedRule().name}`);
+ cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', getEditedRule().description);
cy.get(ABOUT_DETAILS).within(() => {
- getDetails(SEVERITY_DETAILS).should('have.text', editedRule.severity);
- getDetails(RISK_SCORE_DETAILS).should('have.text', editedRule.riskScore);
+ getDetails(SEVERITY_DETAILS).should('have.text', getEditedRule().severity);
+ getDetails(RISK_SCORE_DETAILS).should('have.text', getEditedRule().riskScore);
getDetails(TAGS_DETAILS).should('have.text', expectedEditedtags);
});
cy.get(INVESTIGATION_NOTES_TOGGLE).click({ force: true });
- cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', editedRule.note);
+ cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', getEditedRule().note);
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should(
'have.text',
expectedEditedIndexPatterns.join('')
);
- getDetails(CUSTOM_QUERY_DETAILS).should('have.text', editedRule.customQuery);
+ getDetails(CUSTOM_QUERY_DETAILS).should('have.text', getEditedRule().customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
});
- if (editedRule.interval) {
+ if (getEditedRule().interval) {
cy.get(SCHEDULE_DETAILS).within(() => {
- getDetails(RUNS_EVERY_DETAILS).should('have.text', editedRule.interval);
+ getDetails(RUNS_EVERY_DETAILS).should('have.text', getEditedRule().interval);
});
}
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts
index 337e2a8ec5033e..677a9b55464948 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/event_correlation_rule.spec.ts
@@ -6,7 +6,7 @@
*/
import { formatMitreAttackDescription } from '../../helpers/rules';
-import { eqlRule, eqlSequenceRule, indexPatterns } from '../../objects/rule';
+import { getEqlRule, getEqlSequenceRule, getIndexPatterns } from '../../objects/rule';
import {
ALERT_RULE_METHOD,
@@ -78,20 +78,20 @@ import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import { ALERTS_URL } from '../../urls/navigation';
describe('Detection rules, EQL', () => {
- const expectedUrls = eqlRule.referenceUrls.join('');
- const expectedFalsePositives = eqlRule.falsePositivesExamples.join('');
- const expectedTags = eqlRule.tags.join('');
- const expectedMitre = formatMitreAttackDescription(eqlRule.mitre);
+ const expectedUrls = getEqlRule().referenceUrls.join('');
+ const expectedFalsePositives = getEqlRule().falsePositivesExamples.join('');
+ const expectedTags = getEqlRule().tags.join('');
+ const expectedMitre = formatMitreAttackDescription(getEqlRule().mitre);
const expectedNumberOfRules = 1;
const expectedNumberOfAlerts = 7;
beforeEach(() => {
cleanKibana();
- createTimeline(eqlRule.timeline).then((response) => {
+ createTimeline(getEqlRule().timeline).then((response) => {
cy.wrap({
- ...eqlRule,
+ ...getEqlRule(),
timeline: {
- ...eqlRule.timeline,
+ ...getEqlRule().timeline,
id: response.body.data.persistTimeline.timeline.savedObjectId,
},
}).as('rule');
@@ -148,7 +148,7 @@ describe('Detection rules, EQL', () => {
cy.get(INVESTIGATION_NOTES_TOGGLE).click({ force: true });
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
- getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join(''));
+ getDetails(INDEX_PATTERNS_DETAILS).should('have.text', getIndexPatterns().join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', this.rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Event Correlation');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
@@ -182,11 +182,11 @@ describe('Detection rules, sequence EQL', () => {
beforeEach(() => {
cleanKibana();
- createTimeline(eqlSequenceRule.timeline).then((response) => {
+ createTimeline(getEqlSequenceRule().timeline).then((response) => {
cy.wrap({
- ...eqlSequenceRule,
+ ...getEqlSequenceRule(),
timeline: {
- ...eqlSequenceRule.timeline,
+ ...getEqlSequenceRule().timeline,
id: response.body.data.persistTimeline.timeline.savedObjectId,
},
}).as('rule');
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts
index 1de636010f9670..03086810a84358 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { expectedExportedRule, newRule } from '../../objects/rule';
+import { expectedExportedRule, getNewRule } from '../../objects/rule';
import {
goToManageAlertsDetectionRules,
waitForAlertsIndexToBeCreated,
@@ -28,7 +28,7 @@ describe('Export rules', () => {
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRule(newRule).as('ruleResponse');
+ createCustomRule(getNewRule()).as('ruleResponse');
});
it('Exports a custom rule', function () {
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts
index e1268c52f75d4d..07b40df53e2d5b 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/indicator_match_rule.spec.ts
@@ -6,7 +6,7 @@
*/
import { formatMitreAttackDescription } from '../../helpers/rules';
-import { indexPatterns, newThreatIndicatorRule } from '../../objects/rule';
+import { getIndexPatterns, getNewThreatIndicatorRule } from '../../objects/rule';
import {
ALERT_RULE_METHOD,
@@ -109,10 +109,10 @@ import { ALERTS_URL, RULE_CREATION } from '../../urls/navigation';
describe('indicator match', () => {
describe('Detection rules, Indicator Match', () => {
- const expectedUrls = newThreatIndicatorRule.referenceUrls.join('');
- const expectedFalsePositives = newThreatIndicatorRule.falsePositivesExamples.join('');
- const expectedTags = newThreatIndicatorRule.tags.join('');
- const expectedMitre = formatMitreAttackDescription(newThreatIndicatorRule.mitre);
+ const expectedUrls = getNewThreatIndicatorRule().referenceUrls.join('');
+ const expectedFalsePositives = getNewThreatIndicatorRule().falsePositivesExamples.join('');
+ const expectedTags = getNewThreatIndicatorRule().tags.join('');
+ const expectedMitre = formatMitreAttackDescription(getNewThreatIndicatorRule().mitre);
const expectedNumberOfRules = 1;
const expectedNumberOfAlerts = 1;
@@ -134,12 +134,12 @@ describe('indicator match', () => {
describe('Index patterns', () => {
it('Contains a predefined index pattern', () => {
- getIndicatorIndex().should('have.text', indexPatterns.join(''));
+ getIndicatorIndex().should('have.text', getIndexPatterns().join(''));
});
it('Does NOT show invalidation text on initial page load if indicator index pattern is filled out', () => {
getIndicatorIndicatorIndex().type(
- `${newThreatIndicatorRule.indicatorIndexPattern}{enter}`
+ `${getNewThreatIndicatorRule().indicatorIndexPattern}{enter}`
);
getDefineContinueButton().click();
getIndexPatternInvalidationText().should('not.exist');
@@ -148,7 +148,7 @@ describe('indicator match', () => {
it('Shows invalidation text when you try to continue without filling it out', () => {
getIndexPatternClearButton().click();
getIndicatorIndicatorIndex().type(
- `${newThreatIndicatorRule.indicatorIndexPattern}{enter}`
+ `${getNewThreatIndicatorRule().indicatorIndexPattern}{enter}`
);
getDefineContinueButton().click();
getIndexPatternInvalidationText().should('exist');
@@ -195,8 +195,8 @@ describe('indicator match', () => {
describe('Indicator mapping', () => {
beforeEach(() => {
fillIndexAndIndicatorIndexPattern(
- newThreatIndicatorRule.index,
- newThreatIndicatorRule.indicatorIndexPattern
+ getNewThreatIndicatorRule().index,
+ getNewThreatIndicatorRule().indicatorIndexPattern
);
});
@@ -221,8 +221,8 @@ describe('indicator match', () => {
it('Does NOT show invalidation text when there is a valid "index field" and a valid "indicator index field"', () => {
fillIndicatorMatchRow({
- indexField: newThreatIndicatorRule.indicatorMappingField,
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
});
getDefineContinueButton().click();
getIndicatorInvalidationText().should('not.exist');
@@ -231,7 +231,7 @@ describe('indicator match', () => {
it('Shows invalidation text when there is an invalid "index field" and a valid "indicator index field"', () => {
fillIndicatorMatchRow({
indexField: 'non-existent-value',
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
validColumns: 'indicatorField',
});
getDefineContinueButton().click();
@@ -240,7 +240,7 @@ describe('indicator match', () => {
it('Shows invalidation text when there is a valid "index field" and an invalid "indicator index field"', () => {
fillIndicatorMatchRow({
- indexField: newThreatIndicatorRule.indicatorMappingField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
indicatorIndexField: 'non-existent-value',
validColumns: 'indexField',
});
@@ -250,21 +250,21 @@ describe('indicator match', () => {
it('Deletes the first row when you have two rows. Both rows valid rows of "index fields" and valid "indicator index fields". The second row should become the first row', () => {
fillIndicatorMatchRow({
- indexField: newThreatIndicatorRule.indicatorMappingField,
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
});
getIndicatorAndButton().click();
fillIndicatorMatchRow({
rowNumber: 2,
indexField: 'agent.name',
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
validColumns: 'indicatorField',
});
getIndicatorDeleteButton().click();
getIndicatorIndexComboField().should('have.text', 'agent.name');
getIndicatorMappingComboField().should(
'have.text',
- newThreatIndicatorRule.indicatorIndexField
+ getNewThreatIndicatorRule().indicatorIndexField
);
getIndicatorIndexComboField(2).should('not.exist');
getIndicatorMappingComboField(2).should('not.exist');
@@ -272,14 +272,14 @@ describe('indicator match', () => {
it('Deletes the first row when you have two rows. Both rows have valid "index fields" and invalid "indicator index fields". The second row should become the first row', () => {
fillIndicatorMatchRow({
- indexField: newThreatIndicatorRule.indicatorMappingField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
indicatorIndexField: 'non-existent-value',
validColumns: 'indexField',
});
getIndicatorAndButton().click();
fillIndicatorMatchRow({
rowNumber: 2,
- indexField: newThreatIndicatorRule.indicatorMappingField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
indicatorIndexField: 'second-non-existent-value',
validColumns: 'indexField',
});
@@ -292,14 +292,14 @@ describe('indicator match', () => {
it('Deletes the first row when you have two rows. Both rows have valid "indicator index fields" and invalid "index fields". The second row should become the first row', () => {
fillIndicatorMatchRow({
indexField: 'non-existent-value',
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
validColumns: 'indicatorField',
});
getIndicatorAndButton().click();
fillIndicatorMatchRow({
rowNumber: 2,
indexField: 'second-non-existent-value',
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
validColumns: 'indicatorField',
});
getIndicatorDeleteButton().click();
@@ -310,8 +310,8 @@ describe('indicator match', () => {
it('Deletes the first row of data but not the UI elements and the text defaults back to the placeholder of Search', () => {
fillIndicatorMatchRow({
- indexField: newThreatIndicatorRule.indicatorMappingField,
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
});
getIndicatorDeleteButton().click();
getIndicatorIndexComboField().should('text', 'Search');
@@ -322,8 +322,8 @@ describe('indicator match', () => {
it('Deletes the second row when you have three rows. The first row is valid data, the second row is invalid data, and the third row is valid data. Third row should shift up correctly', () => {
fillIndicatorMatchRow({
- indexField: newThreatIndicatorRule.indicatorMappingField,
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
});
getIndicatorAndButton().click();
fillIndicatorMatchRow({
@@ -335,25 +335,25 @@ describe('indicator match', () => {
getIndicatorAndButton().click();
fillIndicatorMatchRow({
rowNumber: 3,
- indexField: newThreatIndicatorRule.indicatorMappingField,
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
});
getIndicatorDeleteButton(2).click();
getIndicatorIndexComboField(1).should(
'text',
- newThreatIndicatorRule.indicatorMappingField
+ getNewThreatIndicatorRule().indicatorMappingField
);
getIndicatorMappingComboField(1).should(
'text',
- newThreatIndicatorRule.indicatorIndexField
+ getNewThreatIndicatorRule().indicatorIndexField
);
getIndicatorIndexComboField(2).should(
'text',
- newThreatIndicatorRule.indicatorMappingField
+ getNewThreatIndicatorRule().indicatorMappingField
);
getIndicatorMappingComboField(2).should(
'text',
- newThreatIndicatorRule.indicatorIndexField
+ getNewThreatIndicatorRule().indicatorIndexField
);
getIndicatorIndexComboField(3).should('not.exist');
getIndicatorMappingComboField(3).should('not.exist');
@@ -368,17 +368,17 @@ describe('indicator match', () => {
getIndicatorOrButton().click();
fillIndicatorMatchRow({
rowNumber: 2,
- indexField: newThreatIndicatorRule.indicatorMappingField,
- indicatorIndexField: newThreatIndicatorRule.indicatorIndexField,
+ indexField: getNewThreatIndicatorRule().indicatorMappingField,
+ indicatorIndexField: getNewThreatIndicatorRule().indicatorIndexField,
});
getIndicatorDeleteButton().click();
getIndicatorIndexComboField().should(
'text',
- newThreatIndicatorRule.indicatorMappingField
+ getNewThreatIndicatorRule().indicatorMappingField
);
getIndicatorMappingComboField().should(
'text',
- newThreatIndicatorRule.indicatorIndexField
+ getNewThreatIndicatorRule().indicatorIndexField
);
getIndicatorIndexComboField(2).should('not.exist');
getIndicatorMappingComboField(2).should('not.exist');
@@ -399,9 +399,9 @@ describe('indicator match', () => {
waitForRulesTableToBeLoaded();
goToCreateNewRule();
selectIndicatorMatchType();
- fillDefineIndicatorMatchRuleAndContinue(newThreatIndicatorRule);
- fillAboutRuleAndContinue(newThreatIndicatorRule);
- fillScheduleRuleAndContinue(newThreatIndicatorRule);
+ fillDefineIndicatorMatchRuleAndContinue(getNewThreatIndicatorRule());
+ fillAboutRuleAndContinue(getNewThreatIndicatorRule());
+ fillScheduleRuleAndContinue(getNewThreatIndicatorRule());
createAndActivateRule();
cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)');
@@ -417,18 +417,18 @@ describe('indicator match', () => {
cy.get(RULES_TABLE).then(($table) => {
cy.wrap($table.find(RULES_ROW).length).should('eql', 1);
});
- cy.get(RULE_NAME).should('have.text', newThreatIndicatorRule.name);
- cy.get(RISK_SCORE).should('have.text', newThreatIndicatorRule.riskScore);
- cy.get(SEVERITY).should('have.text', newThreatIndicatorRule.severity);
+ cy.get(RULE_NAME).should('have.text', getNewThreatIndicatorRule().name);
+ cy.get(RISK_SCORE).should('have.text', getNewThreatIndicatorRule().riskScore);
+ cy.get(SEVERITY).should('have.text', getNewThreatIndicatorRule().severity);
cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true');
goToRuleDetails();
- cy.get(RULE_NAME_HEADER).should('contain', `${newThreatIndicatorRule.name}`);
- cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newThreatIndicatorRule.description);
+ cy.get(RULE_NAME_HEADER).should('contain', `${getNewThreatIndicatorRule().name}`);
+ cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', getNewThreatIndicatorRule().description);
cy.get(ABOUT_DETAILS).within(() => {
- getDetails(SEVERITY_DETAILS).should('have.text', newThreatIndicatorRule.severity);
- getDetails(RISK_SCORE_DETAILS).should('have.text', newThreatIndicatorRule.riskScore);
+ getDetails(SEVERITY_DETAILS).should('have.text', getNewThreatIndicatorRule().severity);
+ getDetails(RISK_SCORE_DETAILS).should('have.text', getNewThreatIndicatorRule().riskScore);
getDetails(REFERENCE_URLS_DETAILS).should((details) => {
expect(removeExternalLinkText(details.text())).equal(expectedUrls);
});
@@ -444,18 +444,20 @@ describe('indicator match', () => {
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(INDEX_PATTERNS_DETAILS).should(
'have.text',
- newThreatIndicatorRule.index.join('')
+ getNewThreatIndicatorRule().index.join('')
);
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', '*:*');
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Indicator Match');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
getDetails(INDICATOR_INDEX_PATTERNS).should(
'have.text',
- newThreatIndicatorRule.indicatorIndexPattern.join('')
+ getNewThreatIndicatorRule().indicatorIndexPattern.join('')
);
getDetails(INDICATOR_MAPPING).should(
'have.text',
- `${newThreatIndicatorRule.indicatorMappingField} MATCHES ${newThreatIndicatorRule.indicatorIndexField}`
+ `${getNewThreatIndicatorRule().indicatorMappingField} MATCHES ${
+ getNewThreatIndicatorRule().indicatorIndexField
+ }`
);
getDetails(INDICATOR_INDEX_QUERY).should('have.text', '*:*');
});
@@ -463,11 +465,15 @@ describe('indicator match', () => {
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should(
'have.text',
- `${newThreatIndicatorRule.runsEvery.interval}${newThreatIndicatorRule.runsEvery.type}`
+ `${getNewThreatIndicatorRule().runsEvery.interval}${
+ getNewThreatIndicatorRule().runsEvery.type
+ }`
);
getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should(
'have.text',
- `${newThreatIndicatorRule.lookBack.interval}${newThreatIndicatorRule.lookBack.type}`
+ `${getNewThreatIndicatorRule().lookBack.interval}${
+ getNewThreatIndicatorRule().lookBack.type
+ }`
);
});
@@ -475,13 +481,15 @@ describe('indicator match', () => {
waitForAlertsToPopulate();
cy.get(NUMBER_OF_ALERTS).should('have.text', expectedNumberOfAlerts);
- cy.get(ALERT_RULE_NAME).first().should('have.text', newThreatIndicatorRule.name);
+ cy.get(ALERT_RULE_NAME).first().should('have.text', getNewThreatIndicatorRule().name);
cy.get(ALERT_RULE_VERSION).first().should('have.text', '1');
cy.get(ALERT_RULE_METHOD).first().should('have.text', 'threat_match');
cy.get(ALERT_RULE_SEVERITY)
.first()
- .should('have.text', newThreatIndicatorRule.severity.toLowerCase());
- cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', newThreatIndicatorRule.riskScore);
+ .should('have.text', getNewThreatIndicatorRule().severity.toLowerCase());
+ cy.get(ALERT_RULE_RISK_SCORE)
+ .first()
+ .should('have.text', getNewThreatIndicatorRule().riskScore);
});
it('Investigate alert in timeline', () => {
@@ -492,7 +500,7 @@ describe('indicator match', () => {
loadPrepackagedTimelineTemplates();
goToManageAlertsDetectionRules();
- createCustomIndicatorRule(newThreatIndicatorRule);
+ createCustomIndicatorRule(getNewThreatIndicatorRule());
reload();
goToRuleDetails();
@@ -502,13 +510,25 @@ describe('indicator match', () => {
cy.get(PROVIDER_BADGE).should('have.length', 3);
cy.get(PROVIDER_BADGE).should(
'have.text',
- `threat.indicator.matched.atomic: "${newThreatIndicatorRule.atomic}"threat.indicator.matched.type: "indicator_match_rule"threat.indicator.matched.field: "${newThreatIndicatorRule.indicatorMappingField}"`
+ `threat.indicator.matched.atomic: "${
+ getNewThreatIndicatorRule().atomic
+ }"threat.indicator.matched.type: "indicator_match_rule"threat.indicator.matched.field: "${
+ getNewThreatIndicatorRule().indicatorMappingField
+ }"`
);
cy.readFile(threatIndicatorPath).then((threatIndicator) => {
cy.get(INDICATOR_MATCH_ROW_RENDER).should(
'have.text',
- `threat.indicator.matched.field${newThreatIndicatorRule.indicatorMappingField}${accessibilityText}matched${newThreatIndicatorRule.indicatorMappingField}${newThreatIndicatorRule.atomic}${accessibilityText}threat.indicator.matched.typeindicator_match_rule${accessibilityText}fromthreat.indicator.event.dataset${threatIndicator.value.source.event.dataset}${accessibilityText}:threat.indicator.event.reference${threatIndicator.value.source.event.reference}(opens in a new tab or window)${accessibilityText}`
+ `threat.indicator.matched.field${
+ getNewThreatIndicatorRule().indicatorMappingField
+ }${accessibilityText}matched${getNewThreatIndicatorRule().indicatorMappingField}${
+ getNewThreatIndicatorRule().atomic
+ }${accessibilityText}threat.indicator.matched.typeindicator_match_rule${accessibilityText}fromthreat.indicator.event.dataset${
+ threatIndicator.value.source.event.dataset
+ }${accessibilityText}:threat.indicator.event.reference${
+ threatIndicator.value.source.event.reference
+ }(opens in a new tab or window)${accessibilityText}`
);
});
});
@@ -519,7 +539,7 @@ describe('indicator match', () => {
cleanKibana();
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
goToManageAlertsDetectionRules();
- createCustomIndicatorRule(newThreatIndicatorRule);
+ createCustomIndicatorRule(getNewThreatIndicatorRule());
reload();
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/links.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/links.spec.ts
index fdc4bce677f745..85eb68a6cdfa95 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/links.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/links.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import { RULES_MONIROTING_TABLE, RULE_NAME } from '../../screens/alerts_detection_rules';
import { goToManageAlertsDetectionRules, waitForAlertsIndexToBeCreated } from '../../tasks/alerts';
import { createCustomRuleActivated } from '../../tasks/api_calls/rules';
@@ -19,7 +19,7 @@ describe('Rules talbes links', () => {
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
goToManageAlertsDetectionRules();
waitForAlertsIndexToBeCreated();
- createCustomRuleActivated(newRule, 'rule1');
+ createCustomRuleActivated(getNewRule(), 'rule1');
reload();
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/machine_learning_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/machine_learning_rule.spec.ts
index 2d869b314b67ca..e66f8f55be9869 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/machine_learning_rule.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/machine_learning_rule.spec.ts
@@ -6,7 +6,7 @@
*/
import { formatMitreAttackDescription } from '../../helpers/rules';
-import { machineLearningRule } from '../../objects/rule';
+import { getMachineLearningRule } from '../../objects/rule';
import {
CUSTOM_RULES_BTN,
@@ -65,10 +65,10 @@ import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import { ALERTS_URL } from '../../urls/navigation';
describe('Detection rules, machine learning', () => {
- const expectedUrls = machineLearningRule.referenceUrls.join('');
- const expectedFalsePositives = machineLearningRule.falsePositivesExamples.join('');
- const expectedTags = machineLearningRule.tags.join('');
- const expectedMitre = formatMitreAttackDescription(machineLearningRule.mitre);
+ const expectedUrls = getMachineLearningRule().referenceUrls.join('');
+ const expectedFalsePositives = getMachineLearningRule().falsePositivesExamples.join('');
+ const expectedTags = getMachineLearningRule().tags.join('');
+ const expectedMitre = formatMitreAttackDescription(getMachineLearningRule().mitre);
const expectedNumberOfRules = 1;
beforeEach(() => {
@@ -83,9 +83,9 @@ describe('Detection rules, machine learning', () => {
waitForRulesTableToBeLoaded();
goToCreateNewRule();
selectMachineLearningRuleType();
- fillDefineMachineLearningRuleAndContinue(machineLearningRule);
- fillAboutRuleAndContinue(machineLearningRule);
- fillScheduleRuleAndContinue(machineLearningRule);
+ fillDefineMachineLearningRuleAndContinue(getMachineLearningRule());
+ fillAboutRuleAndContinue(getMachineLearningRule());
+ fillScheduleRuleAndContinue(getMachineLearningRule());
createAndActivateRule();
cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)');
@@ -101,18 +101,18 @@ describe('Detection rules, machine learning', () => {
cy.get(RULES_TABLE).then(($table) => {
cy.wrap($table.find(RULES_ROW).length).should('eql', 1);
});
- cy.get(RULE_NAME).should('have.text', machineLearningRule.name);
- cy.get(RISK_SCORE).should('have.text', machineLearningRule.riskScore);
- cy.get(SEVERITY).should('have.text', machineLearningRule.severity);
+ cy.get(RULE_NAME).should('have.text', getMachineLearningRule().name);
+ cy.get(RISK_SCORE).should('have.text', getMachineLearningRule().riskScore);
+ cy.get(SEVERITY).should('have.text', getMachineLearningRule().severity);
cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true');
goToRuleDetails();
- cy.get(RULE_NAME_HEADER).should('contain', `${machineLearningRule.name}`);
- cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', machineLearningRule.description);
+ cy.get(RULE_NAME_HEADER).should('contain', `${getMachineLearningRule().name}`);
+ cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', getMachineLearningRule().description);
cy.get(ABOUT_DETAILS).within(() => {
- getDetails(SEVERITY_DETAILS).should('have.text', machineLearningRule.severity);
- getDetails(RISK_SCORE_DETAILS).should('have.text', machineLearningRule.riskScore);
+ getDetails(SEVERITY_DETAILS).should('have.text', getMachineLearningRule().severity);
+ getDetails(RISK_SCORE_DETAILS).should('have.text', getMachineLearningRule().riskScore);
getDetails(REFERENCE_URLS_DETAILS).should((details) => {
expect(removeExternalLinkText(details.text())).equal(expectedUrls);
});
@@ -125,11 +125,11 @@ describe('Detection rules, machine learning', () => {
cy.get(DEFINITION_DETAILS).within(() => {
getDetails(ANOMALY_SCORE_DETAILS).should(
'have.text',
- machineLearningRule.anomalyScoreThreshold
+ getMachineLearningRule().anomalyScoreThreshold
);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Machine Learning');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
- machineLearningRule.machineLearningJobs.forEach((machineLearningJob, jobIndex) => {
+ getMachineLearningRule().machineLearningJobs.forEach((machineLearningJob, jobIndex) => {
cy.get(MACHINE_LEARNING_JOB_STATUS).eq(jobIndex).should('have.text', 'Stopped');
cy.get(MACHINE_LEARNING_JOB_ID).eq(jobIndex).should('have.text', machineLearningJob);
});
@@ -137,11 +137,11 @@ describe('Detection rules, machine learning', () => {
cy.get(SCHEDULE_DETAILS).within(() => {
getDetails(RUNS_EVERY_DETAILS).should(
'have.text',
- `${machineLearningRule.runsEvery.interval}${machineLearningRule.runsEvery.type}`
+ `${getMachineLearningRule().runsEvery.interval}${getMachineLearningRule().runsEvery.type}`
);
getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should(
'have.text',
- `${machineLearningRule.lookBack.interval}${machineLearningRule.lookBack.type}`
+ `${getMachineLearningRule().lookBack.interval}${getMachineLearningRule().lookBack.type}`
);
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts
index a791cc293c1f06..24a56dd563e174 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/override.spec.ts
@@ -7,9 +7,9 @@
import { formatMitreAttackDescription } from '../../helpers/rules';
import {
- indexPatterns,
- newOverrideRule,
- severitiesOverride,
+ getIndexPatterns,
+ getNewOverrideRule,
+ getSeveritiesOverride,
OverrideRule,
} from '../../objects/rule';
@@ -89,18 +89,18 @@ import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import { ALERTS_URL } from '../../urls/navigation';
describe('Detection rules, override', () => {
- const expectedUrls = newOverrideRule.referenceUrls.join('');
- const expectedFalsePositives = newOverrideRule.falsePositivesExamples.join('');
- const expectedTags = newOverrideRule.tags.join('');
- const expectedMitre = formatMitreAttackDescription(newOverrideRule.mitre);
+ const expectedUrls = getNewOverrideRule().referenceUrls.join('');
+ const expectedFalsePositives = getNewOverrideRule().falsePositivesExamples.join('');
+ const expectedTags = getNewOverrideRule().tags.join('');
+ const expectedMitre = formatMitreAttackDescription(getNewOverrideRule().mitre);
beforeEach(() => {
cleanKibana();
- createTimeline(newOverrideRule.timeline).then((response) => {
+ createTimeline(getNewOverrideRule().timeline).then((response) => {
cy.wrap({
- ...newOverrideRule,
+ ...getNewOverrideRule(),
timeline: {
- ...newOverrideRule.timeline,
+ ...getNewOverrideRule().timeline,
id: response.body.data.persistTimeline.timeline.savedObjectId,
},
}).as('rule');
@@ -167,7 +167,7 @@ describe('Detection rules, override', () => {
.eq(severityOverrideIndex + i)
.should(
'have.text',
- `${severity.sourceField}:${severity.sourceValue}${severitiesOverride[i]}`
+ `${severity.sourceField}:${severity.sourceValue}${getSeveritiesOverride()[i]}`
);
});
});
@@ -175,7 +175,7 @@ describe('Detection rules, override', () => {
cy.get(INVESTIGATION_NOTES_TOGGLE).click({ force: true });
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
- getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join(''));
+ getDetails(INDEX_PATTERNS_DETAILS).should('have.text', getIndexPatterns().join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', this.rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts
index 7d42ea533a9ae5..ef3d3a82d40bd7 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/sorting.spec.ts
@@ -39,7 +39,12 @@ import { DEFAULT_RULE_REFRESH_INTERVAL_VALUE } from '../../../common/constants';
import { ALERTS_URL } from '../../urls/navigation';
import { createCustomRule } from '../../tasks/api_calls/rules';
import { cleanKibana } from '../../tasks/common';
-import { existingRule, newOverrideRule, newRule, newThresholdRule } from '../../objects/rule';
+import {
+ getExistingRule,
+ getNewOverrideRule,
+ getNewRule,
+ getNewThresholdRule,
+} from '../../objects/rule';
describe('Alerts detection rules', () => {
beforeEach(() => {
@@ -47,10 +52,10 @@ describe('Alerts detection rules', () => {
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsPanelToBeLoaded();
waitForAlertsIndexToBeCreated();
- createCustomRule(newRule, '1');
- createCustomRule(existingRule, '2');
- createCustomRule(newOverrideRule, '3');
- createCustomRule(newThresholdRule, '4');
+ createCustomRule(getNewRule(), '1');
+ createCustomRule(getExistingRule(), '2');
+ createCustomRule(getNewOverrideRule(), '3');
+ createCustomRule(getNewThresholdRule(), '4');
});
it('Sorts by activated rules', () => {
@@ -90,8 +95,8 @@ describe('Alerts detection rules', () => {
});
it('Pagination updates page number and results', () => {
- createCustomRule({ ...newRule, name: 'Test a rule' }, '5');
- createCustomRule({ ...newRule, name: 'Not same as first rule' }, '6');
+ createCustomRule({ ...getNewRule(), name: 'Test a rule' }, '5');
+ createCustomRule({ ...getNewRule(), name: 'Not same as first rule' }, '6');
goToManageAlertsDetectionRules();
waitForRulesTableToBeLoaded();
diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts
index ce00c9b40aead9..dba12fb4ab95c2 100644
--- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/threshold_rule.spec.ts
@@ -6,7 +6,12 @@
*/
import { formatMitreAttackDescription } from '../../helpers/rules';
-import { indexPatterns, newRule, newThresholdRule, ThresholdRule } from '../../objects/rule';
+import {
+ getIndexPatterns,
+ getNewRule,
+ getNewThresholdRule,
+ ThresholdRule,
+} from '../../objects/rule';
import {
ALERT_RULE_METHOD,
@@ -84,16 +89,16 @@ import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import { ALERTS_URL } from '../../urls/navigation';
describe('Detection rules, threshold', () => {
- const expectedUrls = newThresholdRule.referenceUrls.join('');
- const expectedFalsePositives = newThresholdRule.falsePositivesExamples.join('');
- const expectedTags = newThresholdRule.tags.join('');
- const expectedMitre = formatMitreAttackDescription(newThresholdRule.mitre);
-
- const rule = { ...newThresholdRule };
+ let rule = getNewThresholdRule();
+ const expectedUrls = getNewThresholdRule().referenceUrls.join('');
+ const expectedFalsePositives = getNewThresholdRule().falsePositivesExamples.join('');
+ const expectedTags = getNewThresholdRule().tags.join('');
+ const expectedMitre = formatMitreAttackDescription(getNewThresholdRule().mitre);
beforeEach(() => {
+ rule = getNewThresholdRule();
cleanKibana();
- createTimeline(newThresholdRule.timeline).then((response) => {
+ createTimeline(getNewThresholdRule().timeline).then((response) => {
rule.timeline.id = response.body.data.persistTimeline.timeline.savedObjectId;
});
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
@@ -149,7 +154,7 @@ describe('Detection rules, threshold', () => {
cy.get(INVESTIGATION_NOTES_TOGGLE).click({ force: true });
cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN);
cy.get(DEFINITION_DETAILS).within(() => {
- getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join(''));
+ getDetails(INDEX_PATTERNS_DETAILS).should('have.text', getIndexPatterns().join(''));
getDetails(CUSTOM_QUERY_DETAILS).should('have.text', rule.customQuery);
getDetails(RULE_TYPE_DETAILS).should('have.text', 'Threshold');
getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None');
@@ -181,15 +186,14 @@ describe('Detection rules, threshold', () => {
});
it('Preview results of keyword using "host.name"', () => {
- const previewRule: ThresholdRule = { ...newThresholdRule };
- previewRule.index = [...previewRule.index, '.siem-signals*'];
+ rule.index = [...rule.index, '.siem-signals*'];
- createCustomRuleActivated(newRule);
+ createCustomRuleActivated(getNewRule());
goToManageAlertsDetectionRules();
waitForRulesTableToBeLoaded();
goToCreateNewRule();
selectThresholdRuleType();
- fillDefineThresholdRule(previewRule);
+ fillDefineThresholdRule(rule);
previewResults();
cy.get(PREVIEW_HEADER_SUBTITLE).should('have.text', '3 unique hits');
@@ -197,13 +201,13 @@ describe('Detection rules, threshold', () => {
it('Preview results of "ip" using "source.ip"', () => {
const previewRule: ThresholdRule = {
- ...newThresholdRule,
+ ...rule,
thresholdField: 'source.ip',
threshold: '1',
};
previewRule.index = [...previewRule.index, '.siem-signals*'];
- createCustomRuleActivated(newRule);
+ createCustomRuleActivated(getNewRule());
goToManageAlertsDetectionRules();
waitForRulesTableToBeLoaded();
goToCreateNewRule();
diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_modal.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_modal.spec.ts
index a4b929f7d8e1d1..7eedc99652f80b 100644
--- a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_modal.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_modal.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { newRule } from '../../objects/rule';
+import { getNewRule } from '../../objects/rule';
import { RULE_STATUS } from '../../screens/create_new_rule';
@@ -44,7 +44,7 @@ describe('Exceptions modal', () => {
cleanKibana();
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsIndexToBeCreated();
- createCustomRule(newRule);
+ createCustomRule(getNewRule());
goToManageAlertsDetectionRules();
goToRuleDetails();
diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts
index 83277075b35cc9..051ebbb9643f69 100644
--- a/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/exceptions_table.spec.ts
@@ -5,8 +5,12 @@
* 2.0.
*/
-import { exception, exceptionList, expectedExportedExceptionList } from '../../objects/exception';
-import { newRule } from '../../objects/rule';
+import {
+ getException,
+ getExceptionList,
+ expectedExportedExceptionList,
+} from '../../objects/exception';
+import { getNewRule } from '../../objects/rule';
import { RULE_STATUS } from '../../screens/create_new_rule';
@@ -46,7 +50,7 @@ describe('Exceptions Table', () => {
cleanKibana();
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsIndexToBeCreated();
- createCustomRule(newRule);
+ createCustomRule(getNewRule());
goToManageAlertsDetectionRules();
goToRuleDetails();
@@ -56,11 +60,11 @@ describe('Exceptions Table', () => {
// Add a detections exception list
goToExceptionsTab();
- addsExceptionFromRuleSettings(exception);
+ addsExceptionFromRuleSettings(getException());
waitForTheRuleToBeExecuted();
// Create exception list not used by any rules
- createExceptionList(exceptionList).as('exceptionListResponse');
+ createExceptionList(getExceptionList()).as('exceptionListResponse');
goBackToAllRulesTable();
waitForRulesTableToBeLoaded();
diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/from_alert.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/from_alert.spec.ts
index 4918de7488dddf..8a683aacd5f666 100644
--- a/x-pack/plugins/security_solution/cypress/integration/exceptions/from_alert.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/from_alert.spec.ts
@@ -5,8 +5,8 @@
* 2.0.
*/
-import { exception } from '../../objects/exception';
-import { newRule } from '../../objects/rule';
+import { getException } from '../../objects/exception';
+import { getNewRule } from '../../objects/rule';
import { ALERTS_COUNT, NUMBER_OF_ALERTS } from '../../screens/alerts';
import { RULE_STATUS } from '../../screens/create_new_rule';
@@ -43,7 +43,7 @@ describe('From alert', () => {
cleanKibana();
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsIndexToBeCreated();
- createCustomRule(newRule, 'rule_testing', '10s');
+ createCustomRule(getNewRule(), 'rule_testing', '10s');
goToManageAlertsDetectionRules();
goToRuleDetails();
@@ -66,7 +66,7 @@ describe('From alert', () => {
it('Creates an exception and deletes it', () => {
addExceptionFromFirstAlert();
- addsException(exception);
+ addsException(getException());
esArchiverLoad('auditbeat_for_exceptions2');
cy.get(ALERTS_COUNT).should('exist');
diff --git a/x-pack/plugins/security_solution/cypress/integration/exceptions/from_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/exceptions/from_rule.spec.ts
index ea8988456d8b30..8fa0050a36521c 100644
--- a/x-pack/plugins/security_solution/cypress/integration/exceptions/from_rule.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/exceptions/from_rule.spec.ts
@@ -5,8 +5,8 @@
* 2.0.
*/
-import { exception } from '../../objects/exception';
-import { newRule } from '../../objects/rule';
+import { getException } from '../../objects/exception';
+import { getNewRule } from '../../objects/rule';
import { ALERTS_COUNT, NUMBER_OF_ALERTS } from '../../screens/alerts';
import { RULE_STATUS } from '../../screens/create_new_rule';
@@ -41,7 +41,7 @@ describe('From rule', () => {
cleanKibana();
loginAndWaitForPageWithoutDateRange(ALERTS_URL);
waitForAlertsIndexToBeCreated();
- createCustomRule(newRule, 'rule_testing', '10s');
+ createCustomRule(getNewRule(), 'rule_testing', '10s');
goToManageAlertsDetectionRules();
goToRuleDetails();
@@ -64,7 +64,7 @@ describe('From rule', () => {
it('Creates an exception and deletes it', () => {
goToExceptionsTab();
- addsExceptionFromRuleSettings(exception);
+ addsExceptionFromRuleSettings(getException());
esArchiverLoad('auditbeat_for_exceptions2');
waitForTheRuleToBeExecuted();
goToAlertsTab();
diff --git a/x-pack/plugins/security_solution/cypress/integration/header/search_bar.spec.ts b/x-pack/plugins/security_solution/cypress/integration/header/search_bar.spec.ts
index d7bef9d67df2fa..c02c2bd9ec1391 100644
--- a/x-pack/plugins/security_solution/cypress/integration/header/search_bar.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/header/search_bar.spec.ts
@@ -8,7 +8,7 @@
import { loginAndWaitForPage } from '../../tasks/login';
import { openAddFilterPopover, fillAddFilterForm } from '../../tasks/search_bar';
import { GLOBAL_SEARCH_BAR_FILTER_ITEM } from '../../screens/search_bar';
-import { hostIpFilter } from '../../objects/filter';
+import { getHostIpFilter } from '../../objects/filter';
import { HOSTS_URL } from '../../urls/navigation';
import { waitForAllHostsToBeLoaded } from '../../tasks/hosts/all_hosts';
@@ -23,11 +23,11 @@ describe('SearchBar', () => {
it('adds correctly a filter to the global search bar', () => {
openAddFilterPopover();
- fillAddFilterForm(hostIpFilter);
+ fillAddFilterForm(getHostIpFilter());
cy.get(GLOBAL_SEARCH_BAR_FILTER_ITEM).should(
'have.text',
- `${hostIpFilter.key}: ${hostIpFilter.value}`
+ `${getHostIpFilter().key}: ${getHostIpFilter().value}`
);
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/overview/overview.spec.ts b/x-pack/plugins/security_solution/cypress/integration/overview/overview.spec.ts
index 3ff036fa0107fe..ca9f83183ab10e 100644
--- a/x-pack/plugins/security_solution/cypress/integration/overview/overview.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/overview/overview.spec.ts
@@ -16,7 +16,7 @@ import overviewFixture from '../../fixtures/overview_search_strategy.json';
import emptyInstance from '../../fixtures/empty_instance.json';
import { cleanKibana } from '../../tasks/common';
import { createTimeline, favoriteTimeline } from '../../tasks/api_calls/timelines';
-import { timeline } from '../../objects/timeline';
+import { getTimeline } from '../../objects/timeline';
describe('Overview Page', () => {
before(() => {
@@ -53,7 +53,7 @@ describe('Overview Page', () => {
describe('Favorite Timelines', () => {
it('should appear on overview page', () => {
- createTimeline(timeline)
+ createTimeline(getTimeline())
.then((response) => response.body.data.persistTimeline.timeline.savedObjectId)
.then((timelineId: string) => {
favoriteTimeline({ timelineId, timelineType: 'default' }).then(() => {
@@ -61,7 +61,7 @@ describe('Overview Page', () => {
loginAndWaitForPage(OVERVIEW_URL);
cy.get('[data-test-subj="overview-recent-timelines"]').should(
'contain',
- timeline.title
+ getTimeline().title
);
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts
index e2c1d7eef38c38..3930088f8bfddc 100644
--- a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts
@@ -5,14 +5,13 @@
* 2.0.
*/
-import { timeline } from '../../objects/timeline';
+import { getTimeline } from '../../objects/timeline';
import {
FAVORITE_TIMELINE,
LOCKED_ICON,
NOTES,
NOTES_TAB_BUTTON,
- // NOTES_COUNT,
NOTES_TEXT_AREA,
PIN_EVENT,
TIMELINE_DESCRIPTION,
@@ -61,7 +60,7 @@ describe('Timeline Templates', () => {
openTimelineUsingToggle();
createNewTimelineTemplate();
populateTimeline();
- addFilter(timeline.filter);
+ addFilter(getTimeline().filter);
cy.get(PIN_EVENT).should(
'have.attr',
'aria-label',
@@ -69,21 +68,21 @@ describe('Timeline Templates', () => {
);
cy.get(LOCKED_ICON).should('be.visible');
- addNameToTimeline(timeline.title);
+ addNameToTimeline(getTimeline().title);
cy.wait('@timeline').then(({ response }) => {
const timelineId = response!.body.data.persistTimeline.timeline.savedObjectId;
- addDescriptionToTimeline(timeline.description);
- addNotesToTimeline(timeline.notes);
+ addDescriptionToTimeline(getTimeline().description);
+ addNotesToTimeline(getTimeline().notes);
markAsFavorite();
waitForTimelineChanges();
createNewTimelineTemplate();
closeTimeline();
openTimelineTemplateFromSettings(timelineId);
- cy.contains(timeline.title).should('exist');
- cy.get(TIMELINES_DESCRIPTION).first().should('have.text', timeline.description);
+ cy.contains(getTimeline().title).should('exist');
+ cy.get(TIMELINES_DESCRIPTION).first().should('have.text', getTimeline().description);
cy.get(TIMELINES_PINNED_EVENT_COUNT).first().should('have.text', '1');
cy.get(TIMELINES_NOTES_COUNT).first().should('have.text', '1');
cy.get(TIMELINES_FAVORITE).first().should('exist');
@@ -91,30 +90,30 @@ describe('Timeline Templates', () => {
openTimeline(timelineId);
cy.get(FAVORITE_TIMELINE).should('exist');
- cy.get(TIMELINE_TITLE).should('have.text', timeline.title);
- cy.get(TIMELINE_DESCRIPTION).should('have.text', timeline.description);
- cy.get(TIMELINE_QUERY).should('have.text', timeline.query);
+ cy.get(TIMELINE_TITLE).should('have.text', getTimeline().title);
+ cy.get(TIMELINE_DESCRIPTION).should('have.text', getTimeline().description);
+ cy.get(TIMELINE_QUERY).should('have.text', getTimeline().query);
// Comments this assertion until we agreed what to do with the filters.
// cy.get(TIMELINE_FILTER(timeline.filter)).should('exist');
// cy.get(NOTES_COUNT).should('have.text', '1');
cy.get(NOTES_TAB_BUTTON).click();
cy.get(NOTES_TEXT_AREA).should('exist');
- cy.get(NOTES).should('have.text', timeline.notes);
+ cy.get(NOTES).should('have.text', getTimeline().notes);
});
});
it('Create template from timeline', () => {
waitForTimelinesPanelToBeLoaded();
- createTimeline(timeline).then(() => {
+ createTimeline(getTimeline()).then(() => {
expandEventAction();
clickingOnCreateTemplateFromTimelineBtn();
cy.wait('@timeline', { timeout: 100000 }).then(({ request }) => {
expect(request.body.timeline).to.haveOwnProperty('templateTimelineId');
- expect(request.body.timeline).to.haveOwnProperty('description', timeline.description);
+ expect(request.body.timeline).to.haveOwnProperty('description', getTimeline().description);
expect(request.body.timeline.kqlQuery.filterQuery.kuery).to.haveOwnProperty(
'expression',
- timeline.query
+ getTimeline().query
);
cy.get(TIMELINE_FLYOUT_WRAPPER).should('have.css', 'visibility', 'visible');
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts
index aa0a6c9308a521..5c2d87c9b727ff 100644
--- a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts
@@ -9,7 +9,7 @@ import { exportTimeline } from '../../tasks/timelines';
import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import {
expectedExportedTimelineTemplate,
- timeline as timelineTemplate,
+ getTimeline as getTimelineTemplate,
} from '../../objects/timeline';
import { TIMELINE_TEMPLATES_URL } from '../../urls/navigation';
@@ -20,7 +20,7 @@ describe('Export timelines', () => {
beforeEach(() => {
cleanKibana();
cy.intercept('POST', 'api/timeline/_export?file_name=timelines_export.ndjson').as('export');
- createTimelineTemplate(timelineTemplate).then((response) => {
+ createTimelineTemplate(getTimelineTemplate()).then((response) => {
cy.wrap(response).as('templateResponse');
cy.wrap(response.body.data.persistTimeline.timeline.savedObjectId).as('templateId');
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts
index 8a90b67682cb2d..4203b9125d1552 100644
--- a/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/timelines/creation.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { timeline } from '../../objects/timeline';
+import { getTimeline } from '../../objects/timeline';
import {
LOCKED_ICON,
@@ -64,7 +64,7 @@ describe('Timelines', (): void => {
before(() => {
openTimelineUsingToggle();
- addNameAndDescriptionToTimeline(timeline);
+ addNameAndDescriptionToTimeline(getTimeline());
populateTimeline();
});
@@ -73,8 +73,8 @@ describe('Timelines', (): void => {
});
it('can be added filter', () => {
- addFilter(timeline.filter);
- cy.get(TIMELINE_FILTER(timeline.filter)).should('exist');
+ addFilter(getTimeline().filter);
+ cy.get(TIMELINE_FILTER(getTimeline().filter)).should('exist');
});
it('pins an event', () => {
@@ -89,8 +89,8 @@ describe('Timelines', (): void => {
});
it('can be added notes', () => {
- addNotesToTimeline(timeline.notes);
- cy.get(NOTES_TEXT).should('have.text', timeline.notes);
+ addNotesToTimeline(getTimeline().notes);
+ cy.get(NOTES_TEXT).should('have.text', getTimeline().notes);
});
it('should update timeline after adding eql', () => {
@@ -116,17 +116,20 @@ describe('Create a timeline from a template', () => {
});
it('Should have the same query and open the timeline modal', () => {
- createTimelineTemplate(timeline).then(() => {
+ createTimelineTemplate(getTimeline()).then(() => {
expandEventAction();
cy.intercept('/api/timeline').as('timeline');
clickingOnCreateTimelineFormTemplateBtn();
cy.wait('@timeline', { timeout: 100000 }).then(({ request }) => {
if (request.body && request.body.timeline) {
- expect(request.body.timeline).to.haveOwnProperty('description', timeline.description);
+ expect(request.body.timeline).to.haveOwnProperty(
+ 'description',
+ getTimeline().description
+ );
expect(request.body.timeline.kqlQuery.filterQuery.kuery).to.haveOwnProperty(
'expression',
- timeline.query
+ getTimeline().query
);
cy.get(TIMELINE_FLYOUT_WRAPPER).should('have.css', 'visibility', 'visible');
}
diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts
index c2bd31c635a703..918a554db5606b 100644
--- a/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts
@@ -10,14 +10,14 @@ import { loginAndWaitForPageWithoutDateRange } from '../../tasks/login';
import { TIMELINES_URL } from '../../urls/navigation';
import { createTimeline } from '../../tasks/api_calls/timelines';
-import { expectedExportedTimeline, timeline } from '../../objects/timeline';
+import { expectedExportedTimeline, getTimeline } from '../../objects/timeline';
import { cleanKibana } from '../../tasks/common';
describe('Export timelines', () => {
beforeEach(() => {
cleanKibana();
cy.intercept('POST', '/api/timeline/_export?file_name=timelines_export.ndjson').as('export');
- createTimeline(timeline).then((response) => {
+ createTimeline(getTimeline()).then((response) => {
cy.wrap(response).as('timelineResponse');
cy.wrap(response.body.data.persistTimeline.timeline.savedObjectId).as('timelineId');
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/notes_tab.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/notes_tab.spec.ts
index 24309b8fda0849..0a784cf952ca66 100644
--- a/x-pack/plugins/security_solution/cypress/integration/timelines/notes_tab.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/timelines/notes_tab.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { timelineNonValidQuery } from '../../objects/timeline';
+import { getTimelineNonValidQuery } from '../../objects/timeline';
import {
NOTES_AUTHOR,
@@ -39,7 +39,7 @@ describe('Timeline notes tab', () => {
loginAndWaitForPageWithoutDateRange(TIMELINES_URL);
waitForTimelinesPanelToBeLoaded();
- createTimeline(timelineNonValidQuery)
+ createTimeline(getTimelineNonValidQuery())
.then((response) => response.body.data.persistTimeline.timeline.savedObjectId)
.then((timelineId: string) =>
refreshTimelinesUntilTimeLinePresent(timelineId)
@@ -56,16 +56,16 @@ describe('Timeline notes tab', () => {
});
it('should render mockdown', () => {
cy.intercept('/api/note').as(`updateNote`);
- addNotesToTimeline(timelineNonValidQuery.notes);
+ addNotesToTimeline(getTimelineNonValidQuery().notes);
cy.wait('@updateNote').its('response.statusCode').should('eq', 200);
cy.get(NOTES_TEXT_AREA).should('exist');
});
it('should contain notes', () => {
cy.intercept('/api/note').as(`updateNote`);
- addNotesToTimeline(timelineNonValidQuery.notes);
+ addNotesToTimeline(getTimelineNonValidQuery().notes);
cy.wait('@updateNote').its('response.statusCode').should('eq', 200);
- cy.get(NOTES_TEXT).first().should('have.text', timelineNonValidQuery.notes);
+ cy.get(NOTES_TEXT).first().should('have.text', getTimelineNonValidQuery().notes);
});
it('should be able to render font in bold', () => {
@@ -91,7 +91,7 @@ describe('Timeline notes tab', () => {
it('should render the right author', () => {
cy.intercept('/api/note').as(`updateNote`);
- addNotesToTimeline(timelineNonValidQuery.notes);
+ addNotesToTimeline(getTimelineNonValidQuery().notes);
cy.wait('@updateNote').its('response.statusCode').should('eq', 200);
cy.get(NOTES_AUTHOR).first().should('have.text', text);
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/open_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/open_timeline.spec.ts
index 814631b2af636a..5c620a983b2b32 100644
--- a/x-pack/plugins/security_solution/cypress/integration/timelines/open_timeline.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/timelines/open_timeline.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { timeline } from '../../objects/timeline';
+import { getTimeline } from '../../objects/timeline';
import { TIMELINE_DESCRIPTION, TIMELINE_TITLE, OPEN_TIMELINE_MODAL } from '../../screens/timeline';
import {
@@ -39,7 +39,7 @@ describe('Open timeline', () => {
loginAndWaitForPageWithoutDateRange(TIMELINES_URL);
waitForTimelinesPanelToBeLoaded();
- createTimeline(timeline)
+ createTimeline(getTimeline())
.then((response) => response.body.data.persistTimeline.timeline.savedObjectId)
.then((timelineId: string) => {
refreshTimelinesUntilTimeLinePresent(timelineId)
@@ -47,7 +47,7 @@ describe('Open timeline', () => {
// request responses and indeterminism since on clicks to activates URL's.
.then(() => cy.wait(1000))
.then(() =>
- addNoteToTimeline(timeline.notes, timelineId).should((response) =>
+ addNoteToTimeline(getTimeline().notes, timelineId).should((response) =>
expect(response.status).to.equal(200)
)
)
@@ -71,11 +71,11 @@ describe('Open timeline', () => {
});
it('should display timeline info - title', () => {
- cy.contains(timeline.title).should('exist');
+ cy.contains(getTimeline().title).should('exist');
});
it('should display timeline info - description', () => {
- cy.get(TIMELINES_DESCRIPTION).first().should('have.text', timeline.description);
+ cy.get(TIMELINES_DESCRIPTION).first().should('have.text', getTimeline().description);
});
it('should display timeline info - pinned event count', () => {
@@ -91,11 +91,11 @@ describe('Open timeline', () => {
});
it('should display timeline content - title', () => {
- cy.get(TIMELINE_TITLE).should('have.text', timeline.title);
+ cy.get(TIMELINE_TITLE).should('have.text', getTimeline().title);
});
it('should display timeline content - description', () => {
- cy.get(TIMELINE_DESCRIPTION).should('have.text', timeline.description);
+ cy.get(TIMELINE_DESCRIPTION).should('have.text', getTimeline().description);
});
});
});
diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/query_tab.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/query_tab.spec.ts
index f37a66ac048fb1..06891121d63543 100644
--- a/x-pack/plugins/security_solution/cypress/integration/timelines/query_tab.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/timelines/query_tab.spec.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { timeline } from '../../objects/timeline';
+import { getTimeline } from '../../objects/timeline';
import {
UNLOCKED_ICON,
@@ -38,7 +38,7 @@ describe('Timeline query tab', () => {
loginAndWaitForPageWithoutDateRange(TIMELINES_URL);
waitForTimelinesPanelToBeLoaded();
- createTimeline(timeline)
+ createTimeline(getTimeline())
.then((response) => response.body.data.persistTimeline.timeline.savedObjectId)
.then((timelineId: string) => {
refreshTimelinesUntilTimeLinePresent(timelineId)
@@ -46,14 +46,14 @@ describe('Timeline query tab', () => {
// request responses and indeterminism since on clicks to activates URL's.
.then(() => cy.wait(1000))
.then(() =>
- addNoteToTimeline(timeline.notes, timelineId).should((response) =>
+ addNoteToTimeline(getTimeline().notes, timelineId).should((response) =>
expect(response.status).to.equal(200)
)
)
.then(() => openTimelineById(timelineId))
.then(() => pinFirstEvent())
.then(() => persistNoteToFirstEvent('event note'))
- .then(() => addFilter(timeline.filter));
+ .then(() => addFilter(getTimeline().filter));
});
});
@@ -63,7 +63,7 @@ describe('Timeline query tab', () => {
});
it('should contain the right query', () => {
- cy.get(TIMELINE_QUERY).should('have.text', `${timeline.query}`);
+ cy.get(TIMELINE_QUERY).should('have.text', `${getTimeline().query}`);
});
it('should be able to add event note', () => {
@@ -71,7 +71,7 @@ describe('Timeline query tab', () => {
});
it('should display timeline filter', () => {
- cy.get(TIMELINE_FILTER(timeline.filter)).should('exist');
+ cy.get(TIMELINE_FILTER(getTimeline().filter)).should('exist');
});
it('should display pinned events', () => {
diff --git a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts b/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts
index 842dd85b42ef8b..a72657d78b70d5 100644
--- a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts
+++ b/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts
@@ -37,7 +37,7 @@ import { addNameToTimeline, closeTimeline, populateTimeline } from '../../tasks/
import { HOSTS_URL } from '../../urls/navigation';
import { ABSOLUTE_DATE_RANGE } from '../../urls/state';
-import { timeline } from '../../objects/timeline';
+import { getTimeline } from '../../objects/timeline';
import { TIMELINE } from '../../screens/create_new_case';
import { cleanKibana } from '../../tasks/common';
@@ -244,7 +244,7 @@ describe('url state', () => {
cy.intercept('PATCH', '/api/timeline').as('timeline');
- addNameToTimeline(timeline.title);
+ addNameToTimeline(getTimeline().title);
cy.wait('@timeline').then(({ response }) => {
closeTimeline();
@@ -256,7 +256,7 @@ describe('url state', () => {
cy.get(DATE_PICKER_APPLY_BUTTON_TIMELINE).should('not.have.text', 'Updating');
cy.get(TIMELINE).should('be.visible');
cy.get(TIMELINE_TITLE).should('be.visible');
- cy.get(TIMELINE_TITLE).should('have.text', timeline.title);
+ cy.get(TIMELINE_TITLE).should('have.text', getTimeline().title);
});
});
});
diff --git a/x-pack/plugins/security_solution/cypress/objects/case.ts b/x-pack/plugins/security_solution/cypress/objects/case.ts
index 847236688dee74..8bc90c5fa2a3be 100644
--- a/x-pack/plugins/security_solution/cypress/objects/case.ts
+++ b/x-pack/plugins/security_solution/cypress/objects/case.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { CompleteTimeline, timeline } from './timeline';
+import { CompleteTimeline, getTimeline } from './timeline';
export interface TestCase extends TestCaseWithoutTimeline {
timeline: CompleteTimeline;
@@ -43,49 +43,50 @@ export interface IbmResilientConnectorOptions {
incidentTypes: string[];
}
-export const case1: TestCase = {
+export const getCase1 = (): TestCase => ({
name: 'This is the title of the case',
tags: ['Tag1', 'Tag2'],
description: 'This is the case description',
- timeline,
+ timeline: getTimeline(),
reporter: 'elastic',
owner: 'securitySolution',
-};
+});
-export const serviceNowConnector: Connector = {
+export const getServiceNowConnector = (): Connector => ({
connectorName: 'New connector',
URL: 'https://www.test.service-now.com',
username: 'Username Name',
password: 'password',
-};
+});
-export const jiraConnectorOptions: JiraConnectorOptions = {
+export const getJiraConnectorOptions = (): JiraConnectorOptions => ({
issueType: '10006',
priority: 'High',
-};
+});
-export const serviceNowConnectorOpions: ServiceNowconnectorOptions = {
+export const getServiceNowConnectorOptions = (): ServiceNowconnectorOptions => ({
urgency: '2',
severity: '1',
impact: '3',
-};
+});
-export const ibmResilientConnectorOptions: IbmResilientConnectorOptions = {
+export const getIbmResilientConnectorOptions = (): IbmResilientConnectorOptions => ({
title: 'Resilient',
severity: 'Medium',
incidentTypes: ['Communication error (fax; email)', 'Denial of Service'],
-};
+});
export const TIMELINE_CASE_ID = '68248e00-f689-11ea-9ab2-59238b522856';
-export const connectorIds = {
+
+export const getConnectorIds = () => ({
jira: '000e5f86-08b0-4882-adfd-6df981d45c1b',
sn: '93a69ba3-3c31-4b4c-bf86-cc79a090f437',
resilient: 'a6a8dd7f-7e88-48fe-9b9f-70b668da8cbc',
-};
+});
-export const mockConnectorsResponse = [
+export const getMockConnectorsResponse = () => [
{
- id: connectorIds.jira,
+ id: getConnectorIds().jira,
actionTypeId: '.jira',
name: 'Jira',
config: {
@@ -96,7 +97,7 @@ export const mockConnectorsResponse = [
referencedByCount: 0,
},
{
- id: connectorIds.resilient,
+ id: getConnectorIds().resilient,
actionTypeId: '.resilient',
name: 'Resilient',
config: {
@@ -107,7 +108,7 @@ export const mockConnectorsResponse = [
referencedByCount: 0,
},
{
- id: connectorIds.sn,
+ id: getConnectorIds().sn,
actionTypeId: '.servicenow',
name: 'ServiceNow',
config: {
@@ -117,7 +118,8 @@ export const mockConnectorsResponse = [
referencedByCount: 0,
},
];
-export const executeResponses = {
+
+export const getExecuteResponses = () => ({
servicenow: {
choices: {
status: 'ok',
@@ -208,7 +210,7 @@ export const executeResponses = {
{ id: '10006', name: 'Task' },
{ id: '10007', name: 'Sub-task' },
],
- actionId: connectorIds.jira,
+ actionId: getConnectorIds().jira,
},
fieldsByIssueType: {
status: 'ok',
@@ -299,7 +301,7 @@ export const executeResponses = {
timetracking: { allowedValues: [], defaultValue: {} },
labels: { allowedValues: [], defaultValue: {} },
},
- actionId: connectorIds.jira,
+ actionId: getConnectorIds().jira,
},
},
resilient: {
@@ -309,7 +311,7 @@ export const executeResponses = {
{ id: 17, name: 'Communication error (fax; email)' },
{ id: 21, name: 'Denial of Service' },
],
- actionId: connectorIds.resilient,
+ actionId: getConnectorIds().resilient,
},
severity: {
status: 'ok',
@@ -318,7 +320,7 @@ export const executeResponses = {
{ id: 5, name: 'Medium' },
{ id: 6, name: 'High' },
],
- actionId: connectorIds.resilient,
+ actionId: getConnectorIds().resilient,
},
},
-};
+});
diff --git a/x-pack/plugins/security_solution/cypress/objects/connector.ts b/x-pack/plugins/security_solution/cypress/objects/connector.ts
index 2a0f1cc43eff0e..a5244583bf4943 100644
--- a/x-pack/plugins/security_solution/cypress/objects/connector.ts
+++ b/x-pack/plugins/security_solution/cypress/objects/connector.ts
@@ -14,11 +14,11 @@ export interface EmailConnector {
password: string;
}
-export const emailConnector: EmailConnector = {
+export const getEmailConnector = (): EmailConnector => ({
name: 'Test connector',
from: 'test@example.com',
host: 'example.com',
port: '80',
user: 'username',
password: 'password',
-};
+});
diff --git a/x-pack/plugins/security_solution/cypress/objects/exception.ts b/x-pack/plugins/security_solution/cypress/objects/exception.ts
index 73457f10ccec6f..6a934e1ec46517 100644
--- a/x-pack/plugins/security_solution/cypress/objects/exception.ts
+++ b/x-pack/plugins/security_solution/cypress/objects/exception.ts
@@ -20,22 +20,22 @@ export interface ExceptionList {
type: 'detection' | 'endpoint';
}
-export const exceptionList: ExceptionList = {
+export const getExceptionList = (): ExceptionList => ({
description: 'Test exception list description',
list_id: 'test_exception_list',
name: 'Test exception list',
namespace_type: 'single',
tags: ['test tag'],
type: 'detection',
-};
+});
-export const exception: Exception = {
+export const getException = (): Exception => ({
field: 'host.name',
operator: 'is',
values: ['suricata-iowa'],
-};
+});
-export const expectedExportedExceptionList = (exceptionListResponse: Cypress.Response) => {
+export const expectedExportedExceptionList = (exceptionListResponse: Cypress.Response): string => {
const jsonrule = exceptionListResponse.body;
return `{"_version":"${jsonrule._version}","created_at":"${jsonrule.created_at}","created_by":"elastic","description":"${jsonrule.description}","id":"${jsonrule.id}","immutable":false,"list_id":"test_exception_list","name":"Test exception list","namespace_type":"single","os_types":[],"tags":[],"tie_breaker_id":"${jsonrule.tie_breaker_id}","type":"detection","updated_at":"${jsonrule.updated_at}","updated_by":"elastic","version":1}\n"\n""\n{"exception_list_items_details":"{"exported_count":0}\n"}`;
diff --git a/x-pack/plugins/security_solution/cypress/objects/filter.ts b/x-pack/plugins/security_solution/cypress/objects/filter.ts
index b00954de174222..5a69100a4b38a1 100644
--- a/x-pack/plugins/security_solution/cypress/objects/filter.ts
+++ b/x-pack/plugins/security_solution/cypress/objects/filter.ts
@@ -10,7 +10,7 @@ export interface SearchBarFilter {
value: string;
}
-export const hostIpFilter: SearchBarFilter = {
+export const getHostIpFilter = (): SearchBarFilter => ({
key: 'host.ip',
value: '1.1.1.1',
-};
+});
diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts
index 3383ef4996eadb..a10fa5b0eda78c 100644
--- a/x-pack/plugins/security_solution/cypress/objects/rule.ts
+++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts
@@ -7,8 +7,8 @@
/* eslint-disable @kbn/eslint/no-restricted-paths */
import { rawRules } from '../../server/lib/detection_engine/rules/prepackaged_rules/index';
-import { mockThreatData } from '../../public/detections/mitre/mitre_tactics_techniques';
-import { timeline, CompleteTimeline, indicatorMatchTimelineTemplate } from './timeline';
+import { getMockThreatData } from '../../public/detections/mitre/mitre_tactics_techniques';
+import { getTimeline, CompleteTimeline, getIndicatorMatchTimelineTemplate } from './timeline';
export const totalNumberOfPrebuiltRules = rawRules.length;
@@ -96,7 +96,7 @@ export interface MachineLearningRule {
lookBack: Interval;
}
-export const indexPatterns = [
+export const getIndexPatterns = (): string[] => [
'apm-*-transaction*',
'auditbeat-*',
'endgame-*',
@@ -106,67 +106,69 @@ export const indexPatterns = [
'winlogbeat-*',
];
-const { tactic, technique, subtechnique } = mockThreatData;
-
-const mitre1: Mitre = {
- tactic: `${tactic.name} (${tactic.id})`,
+const getMitre1 = (): Mitre => ({
+ tactic: `${getMockThreatData().tactic.name} (${getMockThreatData().tactic.id})`,
techniques: [
{
- name: `${technique.name} (${technique.id})`,
- subtechniques: [`${subtechnique.name} (${subtechnique.id})`],
+ name: `${getMockThreatData().technique.name} (${getMockThreatData().technique.id})`,
+ subtechniques: [
+ `${getMockThreatData().subtechnique.name} (${getMockThreatData().subtechnique.id})`,
+ ],
},
{
- name: `${technique.name} (${technique.id})`,
+ name: `${getMockThreatData().technique.name} (${getMockThreatData().technique.id})`,
subtechniques: [],
},
],
-};
+});
-const mitre2: Mitre = {
- tactic: `${tactic.name} (${tactic.id})`,
+const getMitre2 = (): Mitre => ({
+ tactic: `${getMockThreatData().tactic.name} (${getMockThreatData().tactic.id})`,
techniques: [
{
- name: `${technique.name} (${technique.id})`,
- subtechniques: [`${subtechnique.name} (${subtechnique.id})`],
+ name: `${getMockThreatData().technique.name} (${getMockThreatData().technique.id})`,
+ subtechniques: [
+ `${getMockThreatData().subtechnique.name} (${getMockThreatData().subtechnique.id})`,
+ ],
},
],
-};
+});
-const severityOverride1: SeverityOverride = {
+const getSeverityOverride1 = (): SeverityOverride => ({
sourceField: 'host.name',
sourceValue: 'host',
-};
+});
-const severityOverride2: SeverityOverride = {
+const getSeverityOverride2 = (): SeverityOverride => ({
sourceField: '@timestamp',
sourceValue: '10/02/2020',
-};
+});
-const severityOverride3: SeverityOverride = {
+const getSeverityOverride3 = (): SeverityOverride => ({
sourceField: 'host.geo.name',
sourceValue: 'atack',
-};
+});
-const severityOverride4: SeverityOverride = {
+const getSeverityOverride4 = (): SeverityOverride => ({
sourceField: 'agent.type',
sourceValue: 'auditbeat',
-};
+});
-const runsEvery: Interval = {
+const getRunsEvery = (): Interval => ({
interval: '1',
timeType: 'Seconds',
type: 's',
-};
+});
-const lookBack: Interval = {
+const getLookBack = (): Interval => ({
interval: '17520',
timeType: 'Hours',
type: 'h',
-};
+});
-export const newRule: CustomRule = {
+export const getNewRule = (): CustomRule => ({
customQuery: 'host.name: *',
- index: indexPatterns,
+ index: getIndexPatterns(),
name: 'New Rule Test',
description: 'The new rule description.',
severity: 'High',
@@ -174,15 +176,15 @@ export const newRule: CustomRule = {
tags: ['test', 'newRule'],
referenceUrls: ['http://example.com/', 'https://example.com/'],
falsePositivesExamples: ['False1', 'False2'],
- mitre: [mitre1, mitre2],
+ mitre: [getMitre1(), getMitre2()],
note: '# test markdown',
- runsEvery,
- lookBack,
- timeline,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+ timeline: getTimeline(),
maxSignals: 100,
-};
+});
-export const unmappedRule: CustomRule = {
+export const getUnmappedRule = (): CustomRule => ({
customQuery: '*:*',
index: ['unmapped*'],
name: 'Rule with unmapped fields',
@@ -192,15 +194,15 @@ export const unmappedRule: CustomRule = {
tags: ['test', 'newRule'],
referenceUrls: ['http://example.com/', 'https://example.com/'],
falsePositivesExamples: ['False1', 'False2'],
- mitre: [mitre1, mitre2],
+ mitre: [getMitre1(), getMitre2()],
note: '# test markdown',
- runsEvery,
- lookBack,
- timeline,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+ timeline: getTimeline(),
maxSignals: 100,
-};
+});
-export const unmappedCCSRule: CustomRule = {
+export const getUnmappedCCSRule = (): CustomRule => ({
customQuery: '*:*',
index: [`${ccsRemoteName}:unmapped*`],
name: 'Rule with unmapped fields',
@@ -210,15 +212,15 @@ export const unmappedCCSRule: CustomRule = {
tags: ['test', 'newRule'],
referenceUrls: ['http://example.com/', 'https://example.com/'],
falsePositivesExamples: ['False1', 'False2'],
- mitre: [mitre1, mitre2],
+ mitre: [getMitre1(), getMitre2()],
note: '# test markdown',
- runsEvery,
- lookBack,
- timeline,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+ timeline: getTimeline(),
maxSignals: 100,
-};
+});
-export const existingRule: CustomRule = {
+export const getExistingRule = (): CustomRule => ({
customQuery: 'host.name: *',
name: 'Rule 1',
description: 'Description for Rule 1',
@@ -231,17 +233,17 @@ export const existingRule: CustomRule = {
falsePositivesExamples: [],
mitre: [],
note: 'This is my note',
- runsEvery,
- lookBack,
- timeline,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+ timeline: getTimeline(),
// Please do not change, or if you do, needs
// to be any number other than default value
maxSignals: 500,
-};
+});
-export const newOverrideRule: OverrideRule = {
+export const getNewOverrideRule = (): OverrideRule => ({
customQuery: 'host.name: *',
- index: indexPatterns,
+ index: getIndexPatterns(),
name: 'Override Rule',
description: 'The new rule description.',
severity: 'High',
@@ -249,21 +251,26 @@ export const newOverrideRule: OverrideRule = {
tags: ['test', 'newRule'],
referenceUrls: ['http://example.com/', 'https://example.com/'],
falsePositivesExamples: ['False1', 'False2'],
- mitre: [mitre1, mitre2],
+ mitre: [getMitre1(), getMitre2()],
note: '# test markdown',
- severityOverride: [severityOverride1, severityOverride2, severityOverride3, severityOverride4],
+ severityOverride: [
+ getSeverityOverride1(),
+ getSeverityOverride2(),
+ getSeverityOverride3(),
+ getSeverityOverride4(),
+ ],
riskOverride: 'destination.port',
nameOverride: 'agent.type',
timestampOverride: '@timestamp',
- runsEvery,
- lookBack,
- timeline,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+ timeline: getTimeline(),
maxSignals: 100,
-};
+});
-export const newThresholdRule: ThresholdRule = {
+export const getNewThresholdRule = (): ThresholdRule => ({
customQuery: 'host.name: *',
- index: indexPatterns,
+ index: getIndexPatterns(),
name: 'Threshold Rule',
description: 'The new rule description.',
severity: 'High',
@@ -271,17 +278,17 @@ export const newThresholdRule: ThresholdRule = {
tags: ['test', 'newRule'],
referenceUrls: ['http://example.com/', 'https://example.com/'],
falsePositivesExamples: ['False1', 'False2'],
- mitre: [mitre1, mitre2],
+ mitre: [getMitre1(), getMitre2()],
note: '# test markdown',
thresholdField: 'host.name',
threshold: '10',
- runsEvery,
- lookBack,
- timeline,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+ timeline: getTimeline(),
maxSignals: 100,
-};
+});
-export const machineLearningRule: MachineLearningRule = {
+export const getMachineLearningRule = (): MachineLearningRule => ({
machineLearningJobs: ['linux_anomalous_network_service', 'linux_anomalous_network_activity_ecs'],
anomalyScoreThreshold: '20',
name: 'New ML Rule Test',
@@ -291,52 +298,52 @@ export const machineLearningRule: MachineLearningRule = {
tags: ['ML'],
referenceUrls: ['https://elastic.co/'],
falsePositivesExamples: ['False1'],
- mitre: [mitre1],
+ mitre: [getMitre1()],
note: '# test markdown',
- runsEvery,
- lookBack,
-};
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+});
-export const eqlRule: CustomRule = {
+export const getEqlRule = (): CustomRule => ({
customQuery: 'any where process.name == "which"',
name: 'New EQL Rule',
- index: indexPatterns,
+ index: getIndexPatterns(),
description: 'New EQL rule description.',
severity: 'High',
riskScore: '17',
tags: ['test', 'newRule'],
referenceUrls: ['http://example.com/', 'https://example.com/'],
falsePositivesExamples: ['False1', 'False2'],
- mitre: [mitre1, mitre2],
+ mitre: [getMitre1(), getMitre2()],
note: '# test markdown',
- runsEvery,
- lookBack,
- timeline,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+ timeline: getTimeline(),
maxSignals: 100,
-};
+});
-export const eqlSequenceRule: CustomRule = {
+export const getEqlSequenceRule = (): CustomRule => ({
customQuery:
'sequence with maxspan=30s\
[any where process.name == "which"]\
[any where process.name == "xargs"]',
name: 'New EQL Sequence Rule',
- index: indexPatterns,
+ index: getIndexPatterns(),
description: 'New EQL rule description.',
severity: 'High',
riskScore: '17',
tags: ['test', 'newRule'],
referenceUrls: ['http://example.com/', 'https://example.com/'],
falsePositivesExamples: ['False1', 'False2'],
- mitre: [mitre1, mitre2],
+ mitre: [getMitre1(), getMitre2()],
note: '# test markdown',
- runsEvery,
- lookBack,
- timeline,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
+ timeline: getTimeline(),
maxSignals: 100,
-};
+});
-export const newThreatIndicatorRule: ThreatIndicatorRule = {
+export const getNewThreatIndicatorRule = (): ThreatIndicatorRule => ({
name: 'Threat Indicator Rule Test',
description: 'The threat indicator rule description.',
index: ['suspicious-*'],
@@ -345,31 +352,31 @@ export const newThreatIndicatorRule: ThreatIndicatorRule = {
tags: ['test', 'threat'],
referenceUrls: ['http://example.com/', 'https://example.com/'],
falsePositivesExamples: ['False1', 'False2'],
- mitre: [mitre1, mitre2],
+ mitre: [getMitre1(), getMitre2()],
note: '# test markdown',
- runsEvery,
- lookBack,
+ runsEvery: getRunsEvery(),
+ lookBack: getLookBack(),
indicatorIndexPattern: ['filebeat-*'],
indicatorMappingField: 'myhash.mysha256',
indicatorIndexField: 'threatintel.indicator.file.hash.sha256',
type: 'file',
atomic: 'a04ac6d98ad989312783d4fe3456c53730b212c79a426fb215708b6c6daa3de3',
- timeline: indicatorMatchTimelineTemplate,
+ timeline: getIndicatorMatchTimelineTemplate(),
maxSignals: 100,
-};
+});
-export const duplicatedRuleName = `${newThreatIndicatorRule.name} [Duplicate]`;
+export const duplicatedRuleName = `${getNewThreatIndicatorRule().name} [Duplicate]`;
-export const severitiesOverride = ['Low', 'Medium', 'High', 'Critical'];
+export const getSeveritiesOverride = (): string[] => ['Low', 'Medium', 'High', 'Critical'];
-export const editedRule = {
- ...existingRule,
+export const getEditedRule = (): CustomRule => ({
+ ...getExistingRule(),
severity: 'Medium',
description: 'Edited Rule description',
- tags: [...existingRule.tags, 'edited'],
-};
+ tags: [...getExistingRule().tags, 'edited'],
+});
-export const expectedExportedRule = (ruleResponse: Cypress.Response) => {
+export const expectedExportedRule = (ruleResponse: Cypress.Response): string => {
const jsonrule = ruleResponse.body;
return `{"id":"${jsonrule.id}","updated_at":"${jsonrule.updated_at}","updated_by":"elastic","created_at":"${jsonrule.created_at}","created_by":"elastic","name":"${jsonrule.name}","tags":[],"interval":"100m","enabled":false,"description":"${jsonrule.description}","risk_score":${jsonrule.risk_score},"severity":"${jsonrule.severity}","output_index":".siem-signals-default","author":[],"false_positives":[],"from":"now-17520h","rule_id":"rule_testing","max_signals":100,"risk_score_mapping":[],"severity_mapping":[],"threat":[],"to":"now","references":[],"version":1,"exceptions_list":[],"immutable":false,"type":"query","language":"kuery","index":["exceptions-*"],"query":"${jsonrule.query}","throttle":"no_actions","actions":[]}\n{"exported_count":1,"missing_rules":[],"missing_rules_count":0}\n`;
diff --git a/x-pack/plugins/security_solution/cypress/objects/timeline.ts b/x-pack/plugins/security_solution/cypress/objects/timeline.ts
index 1b66b50605508a..c13c1b01ef0ed6 100644
--- a/x-pack/plugins/security_solution/cypress/objects/timeline.ts
+++ b/x-pack/plugins/security_solution/cypress/objects/timeline.ts
@@ -24,51 +24,51 @@ export interface TimelineFilter {
value?: string;
}
-export const filter: TimelineFilter = {
+export const getFilter = (): TimelineFilter => ({
field: 'host.name',
operator: 'exists',
value: 'exists',
-};
+});
-export const timeline: CompleteTimeline = {
+export const getTimeline = (): CompleteTimeline => ({
title: 'Security Timeline',
description: 'This is the best timeline',
query: 'host.name: *',
notes: 'Yes, the best timeline',
- filter,
-};
+ filter: getFilter(),
+});
-export const indicatorMatchTimelineTemplate: CompleteTimeline = {
- ...timeline,
+export const getIndicatorMatchTimelineTemplate = (): CompleteTimeline => ({
+ ...getTimeline(),
title: 'Generic Threat Match Timeline',
templateTimelineId: '495ad7a7-316e-4544-8a0f-9c098daee76e',
-};
+});
/**
* Timeline query that finds no valid data to cut down on test failures
* or other issues for when we want to test one specific thing and not also
* test the queries happening
*/
-export const timelineNonValidQuery: CompleteTimeline = {
- ...timeline,
+export const getTimelineNonValidQuery = (): CompleteTimeline => ({
+ ...getTimeline(),
query: 'query_to_intentionally_find_nothing: *',
-};
+});
-export const caseTimeline: Timeline = {
+export const caseTimeline = (): Timeline => ({
title: 'SIEM test',
description: 'description',
query: 'host.name: *',
id: '0162c130-78be-11ea-9718-118a926974a4',
-};
+});
-export const expectedExportedTimelineTemplate = (templateResponse: Cypress.Response) => {
+export const expectedExportedTimelineTemplate = (templateResponse: Cypress.Response): string => {
const timelineTemplateBody = templateResponse.body.data.persistTimeline.timeline;
return `{"savedObjectId":"${timelineTemplateBody.savedObjectId}","version":"${timelineTemplateBody.version}","columns":[{"id":"@timestamp"},{"id":"user.name"},{"id":"event.category"},{"id":"event.action"},{"id":"host.name"}],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"expression":"${timelineTemplateBody.kqlQuery.filterQuery.kuery.expression}","kind":"kuery"}}},"dateRange":{"start":"${timelineTemplateBody.dateRange.start}","end":"${timelineTemplateBody.dateRange.end}"},"description":"${timelineTemplateBody.description}","title":"${timelineTemplateBody.title}","templateTimelineVersion":1,"timelineType":"template","created":${timelineTemplateBody.created},"createdBy":"elastic","updated":${timelineTemplateBody.updated},"updatedBy":"elastic","sort":[],"eventNotes":[],"globalNotes":[],"pinnedEventIds":[]}
`;
};
-export const expectedExportedTimeline = (timelineResponse: Cypress.Response) => {
+export const expectedExportedTimeline = (timelineResponse: Cypress.Response): string => {
const timelineBody = timelineResponse.body.data.persistTimeline.timeline;
return `{"savedObjectId":"${timelineBody.savedObjectId}","version":"${timelineBody.version}","columns":[{"id":"@timestamp"},{"id":"user.name"},{"id":"event.category"},{"id":"event.action"},{"id":"host.name"}],"kqlMode":"filter","kqlQuery":{"filterQuery":{"kuery":{"expression":"${timelineBody.kqlQuery.filterQuery.kuery.expression}","kind":"kuery"}}},"dateRange":{"start":"${timelineBody.dateRange.start}","end":"${timelineBody.dateRange.end}"},"description":"${timelineBody.description}","title":"${timelineBody.title}","created":${timelineBody.created},"createdBy":"elastic","updated":${timelineBody.updated},"updatedBy":"elastic","timelineType":"default","sort":[],"eventNotes":[],"globalNotes":[],"pinnedEventIds":[]}\n`;
diff --git a/x-pack/plugins/security_solution/cypress/screens/edit_connector.ts b/x-pack/plugins/security_solution/cypress/screens/edit_connector.ts
index 5b353983e5a920..598485b167c9fc 100644
--- a/x-pack/plugins/security_solution/cypress/screens/edit_connector.ts
+++ b/x-pack/plugins/security_solution/cypress/screens/edit_connector.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import { connectorIds } from '../objects/case';
+import { getConnectorIds } from '../objects/case';
export const CONNECTOR_RESILIENT = `[data-test-subj="connector-fields-resilient"]`;
@@ -17,14 +17,16 @@ export const SELECT_INCIDENT_TYPE = `[data-test-subj="incidentTypeComboBox"] inp
export const SELECT_ISSUE_TYPE = `[data-test-subj="issueTypeSelect"]`;
-export const SELECT_JIRA = `[data-test-subj="dropdown-connector-${connectorIds.jira}"]`;
+export const SELECT_JIRA = `[data-test-subj="dropdown-connector-${getConnectorIds().jira}"]`;
export const SELECT_PRIORITY = `[data-test-subj="prioritySelect"]`;
-export const SELECT_RESILIENT = `[data-test-subj="dropdown-connector-${connectorIds.resilient}"]`;
+export const SELECT_RESILIENT = `[data-test-subj="dropdown-connector-${
+ getConnectorIds().resilient
+}"]`;
export const SELECT_SEVERITY = `[data-test-subj="severitySelect"]`;
-export const SELECT_SN = `[data-test-subj="dropdown-connector-${connectorIds.sn}"]`;
+export const SELECT_SN = `[data-test-subj="dropdown-connector-${getConnectorIds().sn}"]`;
export const SELECT_URGENCY = `[data-test-subj="urgencySelect"]`;
diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
index 1b420cd6d1520d..d8d91dc9ca6243 100644
--- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
+++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts
@@ -5,11 +5,11 @@
* 2.0.
*/
-import { emailConnector, EmailConnector } from '../objects/connector';
+import { getEmailConnector, EmailConnector } from '../objects/connector';
import {
CustomRule,
MachineLearningRule,
- machineLearningRule,
+ getMachineLearningRule,
OverrideRule,
ThreatIndicatorRule,
ThresholdRule,
@@ -397,7 +397,7 @@ export const fillIndexAndIndicatorIndexPattern = (
getIndicatorIndicatorIndex().type(`${indicatorIndex}{enter}`);
};
-export const fillEmailConnectorForm = (connector: EmailConnector = emailConnector) => {
+export const fillEmailConnectorForm = (connector: EmailConnector = getEmailConnector()) => {
cy.get(CONNECTOR_NAME_INPUT).type(connector.name);
cy.get(EMAIL_CONNECTOR_FROM_INPUT).type(connector.from);
cy.get(EMAIL_CONNECTOR_HOST_INPUT).type(connector.host);
@@ -478,9 +478,12 @@ export const fillDefineMachineLearningRuleAndContinue = (rule: MachineLearningRu
cy.get(MACHINE_LEARNING_DROPDOWN_INPUT).type(`${machineLearningJob}{enter}`);
cy.get(MACHINE_LEARNING_DROPDOWN_INPUT).type('{esc}');
});
- cy.get(ANOMALY_THRESHOLD_INPUT).type(`{selectall}${machineLearningRule.anomalyScoreThreshold}`, {
- force: true,
- });
+ cy.get(ANOMALY_THRESHOLD_INPUT).type(
+ `{selectall}${getMachineLearningRule().anomalyScoreThreshold}`,
+ {
+ force: true,
+ }
+ );
getDefineContinueButton().should('exist').click({ force: true });
cy.get(MACHINE_LEARNING_DROPDOWN_INPUT).should('not.exist');
diff --git a/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx b/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx
index f93721349fdac0..d7091059012151 100644
--- a/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/endpoint/agent_status.tsx
@@ -20,7 +20,7 @@ export const AgentStatus = React.memo(({ hostStatus }: { hostStatus: HostStatus
>
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json b/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json
index b5480aac27f678..c37be60545ab2e 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/exceptionable_endpoint_fields.json
@@ -2,10 +2,12 @@
"Endpoint.policy.applied.id",
"Target.process.Ext.services",
"Target.process.Ext.user",
+ "Target.process.executable",
"Target.process.hash.md5",
"Target.process.hash.sha1",
"Target.process.hash.sha256",
"Target.process.hash.sha512",
+ "Target.process.name",
"Target.process.parent.hash.md5",
"Target.process.parent.hash.sha1",
"Target.process.parent.hash.sha256",
@@ -17,6 +19,14 @@
"Target.process.pe.original_file_name",
"Target.process.pe.product",
"Target.process.pgid",
+ "Target.process.thread.Ext.start_address_details.allocation_type",
+ "Target.process.thread.Ext.start_address_bytes_disasm_hash",
+ "Target.process.thread.Ext.start_address_allocation_offset",
+ "Target.process.thread.Ext.start_address_details.allocation_size",
+ "Target.process.thread.Ext.start_address_details.region_size",
+ "Target.process.thread.Ext.start_address_details.region_protection",
+ "Target.process.thread.Ext.start_address_details.memory_pe.imphash",
+ "Target.process.thread.Ext.start_address_bytes",
"agent.id",
"agent.type",
"agent.version",
@@ -68,10 +78,13 @@
"host.type",
"process.Ext.services",
"process.Ext.user",
+ "process.Ext.code_signature",
+ "process.executable",
"process.hash.md5",
"process.hash.sha1",
"process.hash.sha256",
"process.hash.sha512",
+ "process.name",
"process.parent.hash.md5",
"process.parent.hash.sha1",
"process.parent.hash.sha256",
@@ -88,5 +101,7 @@
"user.email",
"user.hash",
"user.id",
- "Ransomware.feature"
+ "Ransomware.feature",
+ "Memory_protection.feature",
+ "Memory_protection.self_injection"
]
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx
index 0af83e2cff3b5b..32eb4baad50598 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.test.tsx
@@ -928,5 +928,172 @@ describe('Exception helpers', () => {
},
]);
});
+
+ test('it should return pre-populated memory signature items for event code `memory_signature`', () => {
+ const defaultItems = defaultEndpointExceptionItems('list_id', 'my_rule', {
+ _id: '123',
+ process: {
+ name: 'some name',
+ executable: 'some file path',
+ hash: {
+ sha256: 'some hash',
+ },
+ },
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ Memory_protection: {
+ feature: 'signature',
+ },
+ event: {
+ code: 'memory_signature',
+ },
+ });
+
+ expect(defaultItems[0].entries).toEqual([
+ {
+ field: 'Memory_protection.feature',
+ operator: 'included',
+ type: 'match',
+ value: 'signature',
+ id: '123',
+ },
+ {
+ field: 'process.executable.caseless',
+ operator: 'included',
+ type: 'match',
+ value: 'some file path',
+ id: '123',
+ },
+ {
+ field: 'process.name.caseless',
+ operator: 'included',
+ type: 'match',
+ value: 'some name',
+ id: '123',
+ },
+ {
+ field: 'process.hash.sha256',
+ operator: 'included',
+ type: 'match',
+ value: 'some hash',
+ id: '123',
+ },
+ ]);
+ });
+
+ test('it should return pre-populated memory shellcode items for event code `malicious_thread`', () => {
+ const defaultItems = defaultEndpointExceptionItems('list_id', 'my_rule', {
+ _id: '123',
+ process: {
+ name: 'some name',
+ executable: 'some file path',
+ Ext: {
+ token: {
+ integrity_level_name: 'high',
+ },
+ },
+ },
+ // eslint-disable-next-line @typescript-eslint/naming-convention
+ Memory_protection: {
+ feature: 'shellcode_thread',
+ self_injection: true,
+ },
+ event: {
+ code: 'malicious_thread',
+ },
+ Target: {
+ process: {
+ thread: {
+ Ext: {
+ start_address_allocation_offset: 0,
+ start_address_bytes_disasm_hash: 'a disam hash',
+ start_address_details: {
+ allocation_type: 'PRIVATE',
+ allocation_size: 4000,
+ region_size: 4000,
+ region_protection: 'RWX',
+ memory_pe: {
+ imphash: 'a hash',
+ },
+ },
+ },
+ },
+ },
+ },
+ });
+
+ expect(defaultItems[0].entries).toEqual([
+ {
+ field: 'Memory_protection.feature',
+ operator: 'included',
+ type: 'match',
+ value: 'shellcode_thread',
+ id: '123',
+ },
+ {
+ field: 'Memory_protection.self_injection',
+ operator: 'included',
+ type: 'match',
+ value: 'true',
+ id: '123',
+ },
+ {
+ field: 'process.executable.caseless',
+ operator: 'included',
+ type: 'match',
+ value: 'some file path',
+ id: '123',
+ },
+ {
+ field: 'process.name.caseless',
+ operator: 'included',
+ type: 'match',
+ value: 'some name',
+ id: '123',
+ },
+ {
+ field: 'process.Ext.token.integrity_level_name',
+ operator: 'included',
+ type: 'match',
+ value: 'high',
+ id: '123',
+ },
+ {
+ field: 'Target.process.thread.Ext.start_address_details',
+ type: 'nested',
+ entries: [
+ {
+ field: 'allocation_type',
+ operator: 'included',
+ type: 'match',
+ value: 'PRIVATE',
+ id: '123',
+ },
+ {
+ field: 'allocation_size',
+ operator: 'included',
+ type: 'match',
+ value: '4000',
+ id: '123',
+ },
+ { field: 'region_size', operator: 'included', type: 'match', value: '4000', id: '123' },
+ {
+ field: 'region_protection',
+ operator: 'included',
+ type: 'match',
+ value: 'RWX',
+ id: '123',
+ },
+ {
+ field: 'memory_pe.imphash',
+ operator: 'included',
+ type: 'match',
+ value: 'a hash',
+ id: '123',
+ },
+ ],
+ id: '123',
+ },
+ ]);
+ });
});
});
diff --git a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx
index bfb5c7298f3301..3c8652637a997f 100644
--- a/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx
+++ b/x-pack/plugins/security_solution/public/common/components/exceptions/helpers.tsx
@@ -496,6 +496,139 @@ export const getPrepopulatedRansomwareException = ({
};
};
+export const getPrepopulatedMemorySignatureException = ({
+ listId,
+ ruleName,
+ eventCode,
+ listNamespace = 'agnostic',
+ alertEcsData,
+}: {
+ listId: string;
+ listNamespace?: NamespaceType;
+ ruleName: string;
+ eventCode: string;
+ alertEcsData: Flattened;
+}): ExceptionsBuilderExceptionItem => {
+ const { process } = alertEcsData;
+ return {
+ ...getNewExceptionItem({ listId, namespaceType: listNamespace, ruleName }),
+ entries: addIdToEntries([
+ {
+ field: 'Memory_protection.feature',
+ operator: 'included',
+ type: 'match',
+ value: alertEcsData.Memory_protection?.feature ?? '',
+ },
+ {
+ field: 'process.executable.caseless',
+ operator: 'included',
+ type: 'match',
+ value: process?.executable ?? '',
+ },
+ {
+ field: 'process.name.caseless',
+ operator: 'included',
+ type: 'match',
+ value: process?.name ?? '',
+ },
+ {
+ field: 'process.hash.sha256',
+ operator: 'included',
+ type: 'match',
+ value: process?.hash?.sha256 ?? '',
+ },
+ ]),
+ };
+};
+export const getPrepopulatedMemoryShellcodeException = ({
+ listId,
+ ruleName,
+ eventCode,
+ listNamespace = 'agnostic',
+ alertEcsData,
+}: {
+ listId: string;
+ listNamespace?: NamespaceType;
+ ruleName: string;
+ eventCode: string;
+ alertEcsData: Flattened;
+}): ExceptionsBuilderExceptionItem => {
+ const { process, Target } = alertEcsData;
+ return {
+ ...getNewExceptionItem({ listId, namespaceType: listNamespace, ruleName }),
+ entries: addIdToEntries([
+ {
+ field: 'Memory_protection.feature',
+ operator: 'included',
+ type: 'match',
+ value: alertEcsData.Memory_protection?.feature ?? '',
+ },
+ {
+ field: 'Memory_protection.self_injection',
+ operator: 'included',
+ type: 'match',
+ value: String(alertEcsData.Memory_protection?.self_injection) ?? '',
+ },
+ {
+ field: 'process.executable.caseless',
+ operator: 'included',
+ type: 'match',
+ value: process?.executable ?? '',
+ },
+ {
+ field: 'process.name.caseless',
+ operator: 'included',
+ type: 'match',
+ value: process?.name ?? '',
+ },
+ {
+ field: 'process.Ext.token.integrity_level_name',
+ operator: 'included',
+ type: 'match',
+ value: process?.Ext?.token?.integrity_level_name ?? '',
+ },
+ {
+ field: 'Target.process.thread.Ext.start_address_details',
+ type: 'nested',
+ entries: [
+ {
+ field: 'allocation_type',
+ operator: 'included',
+ type: 'match',
+ value: Target?.process?.thread?.Ext?.start_address_details?.allocation_type ?? '',
+ },
+ {
+ field: 'allocation_size',
+ operator: 'included',
+ type: 'match',
+ value:
+ String(Target?.process?.thread?.Ext?.start_address_details?.allocation_size) ?? '',
+ },
+ {
+ field: 'region_size',
+ operator: 'included',
+ type: 'match',
+ value: String(Target?.process?.thread?.Ext?.start_address_details?.region_size) ?? '',
+ },
+ {
+ field: 'region_protection',
+ operator: 'included',
+ type: 'match',
+ value:
+ String(Target?.process?.thread?.Ext?.start_address_details?.region_protection) ?? '',
+ },
+ {
+ field: 'memory_pe.imphash',
+ operator: 'included',
+ type: 'match',
+ value:
+ String(Target?.process?.thread?.Ext?.start_address_details?.memory_pe?.imphash) ?? '',
+ },
+ ],
+ },
+ ]),
+ };
+};
/**
* Determines whether or not any entries within the given exceptionItems contain values not in the specified ECS mapping
*/
@@ -537,26 +670,45 @@ export const defaultEndpointExceptionItems = (
const { event: alertEvent } = alertEcsData;
const eventCode = alertEvent?.code ?? '';
- if (eventCode === 'ransomware') {
- return getProcessCodeSignature(alertEcsData).map((codeSignature) =>
- getPrepopulatedRansomwareException({
- listId,
- ruleName,
- eventCode,
- codeSignature,
- alertEcsData,
- })
- );
+ switch (eventCode) {
+ case 'memory_signature':
+ return [
+ getPrepopulatedMemorySignatureException({
+ listId,
+ ruleName,
+ eventCode,
+ alertEcsData,
+ }),
+ ];
+ case 'malicious_thread':
+ return [
+ getPrepopulatedMemoryShellcodeException({
+ listId,
+ ruleName,
+ eventCode,
+ alertEcsData,
+ }),
+ ];
+ case 'ransomware':
+ return getProcessCodeSignature(alertEcsData).map((codeSignature) =>
+ getPrepopulatedRansomwareException({
+ listId,
+ ruleName,
+ eventCode,
+ codeSignature,
+ alertEcsData,
+ })
+ );
+ default:
+ // By default return the standard prepopulated Endpoint Exception fields
+ return getFileCodeSignature(alertEcsData).map((codeSignature) =>
+ getPrepopulatedEndpointException({
+ listId,
+ ruleName,
+ eventCode,
+ codeSignature,
+ alertEcsData,
+ })
+ );
}
-
- // By default return the standard prepopulated Endpoint Exception fields
- return getFileCodeSignature(alertEcsData).map((codeSignature) =>
- getPrepopulatedEndpointException({
- listId,
- ruleName,
- eventCode,
- codeSignature,
- alertEcsData,
- })
- );
};
diff --git a/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.test.ts b/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.test.ts
new file mode 100644
index 00000000000000..13699f5dc30607
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.test.ts
@@ -0,0 +1,38 @@
+/*
+ * 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 { shortenCountIntoString } from './shorten_count_into_string';
+
+describe('utils', () => {
+ describe('shortenCountIntoString', () => {
+ it('should not change small numbers', () => {
+ expect(shortenCountIntoString(0)).toBe('0');
+ expect(shortenCountIntoString(9999)).toBe('9999');
+ });
+
+ it('should add K when appropriate', () => {
+ expect(shortenCountIntoString(10000)).toBe('10K');
+ expect(shortenCountIntoString(109000)).toBe('109K');
+ expect(shortenCountIntoString(109800)).toBe('109.8K');
+ expect(shortenCountIntoString(109897)).toBe('109.8K');
+ });
+
+ it('should add M when appropriate', () => {
+ expect(shortenCountIntoString(10000000)).toBe('10M');
+ expect(shortenCountIntoString(109000000)).toBe('109M');
+ expect(shortenCountIntoString(109800000)).toBe('109.8M');
+ expect(shortenCountIntoString(109890000)).toBe('109.8M');
+ });
+
+ it('should add B when appropriate', () => {
+ expect(shortenCountIntoString(10000000000)).toBe('10B');
+ expect(shortenCountIntoString(109000000000)).toBe('109B');
+ expect(shortenCountIntoString(109800000000)).toBe('109.8B');
+ expect(shortenCountIntoString(109890000000)).toBe('109.8B');
+ });
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.ts b/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.ts
new file mode 100644
index 00000000000000..63d2c8f597911b
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/utils/shorten_count_into_string.ts
@@ -0,0 +1,35 @@
+/*
+ * 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 const shortenCountIntoString = (count: number): string => {
+ if (count < 10000) {
+ return count.toString();
+ }
+ const abbreviations = [
+ { magnitude: 1e18, unit: 'E' },
+ { magnitude: 1e15, unit: 'P' },
+ { magnitude: 1e12, unit: 'T' },
+ { magnitude: 1e9, unit: 'B' },
+ { magnitude: 1e6, unit: 'M' },
+ { magnitude: 1e3, unit: 'K' },
+ ];
+ const { magnitude, unit } = abbreviations.find(
+ (abbreviation) => count >= abbreviation.magnitude
+ ) ?? {
+ magnitude: 1,
+ unit: '',
+ };
+
+ return (
+ toFixedWithoutRounding(count / magnitude, 1).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + unit
+ );
+};
+
+const toFixedWithoutRounding = (n: number, p: number) => {
+ const result = n.toFixed(p);
+ return +result <= n ? result : (+result - Math.pow(0.1, p)).toFixed(p);
+};
diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/take_action_dropdown.tsx b/x-pack/plugins/security_solution/public/detections/components/host_isolation/take_action_dropdown.tsx
index a10ad901441ea5..1404f7927d6ec8 100644
--- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/take_action_dropdown.tsx
+++ b/x-pack/plugins/security_solution/public/detections/components/host_isolation/take_action_dropdown.tsx
@@ -10,6 +10,7 @@ import { EuiContextMenuItem, EuiContextMenuPanel, EuiButton, EuiPopover } from '
import { ISOLATE_HOST, UNISOLATE_HOST } from './translations';
import { TAKE_ACTION } from '../alerts_table/alerts_utility_bar/translations';
import { useHostIsolationStatus } from '../../containers/detection_engine/alerts/use_host_isolation_status';
+import { HostStatus } from '../../../../common/endpoint/types';
export const TakeActionDropdown = React.memo(
({
@@ -19,7 +20,9 @@ export const TakeActionDropdown = React.memo(
onChange: (action: 'isolateHost' | 'unisolateHost') => void;
agentId: string;
}) => {
- const { loading, isIsolated: isolationStatus } = useHostIsolationStatus({ agentId });
+ const { loading, isIsolated: isolationStatus, agentStatus } = useHostIsolationStatus({
+ agentId,
+ });
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
const closePopoverHandler = useCallback(() => {
@@ -41,7 +44,7 @@ export const TakeActionDropdown = React.memo(
iconSide="right"
fill
iconType="arrowDown"
- disabled={loading}
+ disabled={loading || agentStatus === HostStatus.UNENROLLED}
onClick={() => {
setIsPopoverOpen(!isPopoverOpen);
}}
@@ -49,7 +52,7 @@ export const TakeActionDropdown = React.memo(
{TAKE_ACTION}
);
- }, [isPopoverOpen, loading]);
+ }, [isPopoverOpen, loading, agentStatus]);
return (
{
const [isIsolated, setIsIsolated] = useState(false);
- const [agentStatus, setAgentStatus] = useState(HostStatus.UNHEALTHY);
+ const [agentStatus, setAgentStatus] = useState();
const [pendingIsolation, setPendingIsolation] = useState(0);
const [pendingUnisolation, setPendingUnisolation] = useState(0);
const [loading, setLoading] = useState(false);
- const { addError } = useAppToasts();
-
useEffect(() => {
const abortCtrl = new AbortController();
// isMounted tracks if a component is mounted before changing state
@@ -55,7 +51,10 @@ export const useHostIsolationStatus = ({
if (error.name === 'AbortError') {
return;
}
- addError(error.message, { title: ISOLATION_STATUS_FAILURE });
+
+ if (isMounted && error.body.statusCode === 404) {
+ setAgentStatus(HostStatus.UNENROLLED);
+ }
}
try {
@@ -65,7 +64,8 @@ export const useHostIsolationStatus = ({
setPendingUnisolation(data[0].pending_actions?.unisolate ?? 0);
}
} catch (error) {
- addError(error.message, { title: ISOLATION_PENDING_FAILURE });
+ // silently catch non-user initiated error
+ return;
}
if (isMounted) {
@@ -87,6 +87,6 @@ export const useHostIsolationStatus = ({
isMounted = false;
abortCtrl.abort();
};
- }, [addError, agentId]);
+ }, [agentId]);
return { loading, isIsolated, agentStatus, pendingIsolation, pendingUnisolation };
};
diff --git a/x-pack/plugins/security_solution/public/detections/mitre/mitre_tactics_techniques.ts b/x-pack/plugins/security_solution/public/detections/mitre/mitre_tactics_techniques.ts
index a5da747787ba6e..f28311d9c96e76 100644
--- a/x-pack/plugins/security_solution/public/detections/mitre/mitre_tactics_techniques.ts
+++ b/x-pack/plugins/security_solution/public/detections/mitre/mitre_tactics_techniques.ts
@@ -10143,7 +10143,7 @@ export const subtechniquesOptions: MitreSubtechniquesOptions[] = [
*
* Is built alongside and sampled from the data in the file so to always be valid with the most up to date MITRE ATT&CK data
*/
-export const mockThreatData = {
+export const getMockThreatData = () => ({
tactic: {
name: 'Privilege Escalation',
id: 'TA0004',
@@ -10162,4 +10162,4 @@ export const mockThreatData = {
tactics: ['privilege-escalation', 'persistence'],
techniqueId: 'T1546',
},
-};
+});
diff --git a/x-pack/plugins/security_solution/public/detections/mitre/valid_threat_mock.ts b/x-pack/plugins/security_solution/public/detections/mitre/valid_threat_mock.ts
index a7de7494e11167..743b143213c220 100644
--- a/x-pack/plugins/security_solution/public/detections/mitre/valid_threat_mock.ts
+++ b/x-pack/plugins/security_solution/public/detections/mitre/valid_threat_mock.ts
@@ -6,9 +6,9 @@
*/
import { Threats } from '@kbn/securitysolution-io-ts-alerting-types';
-import { mockThreatData } from './mitre_tactics_techniques';
+import { getMockThreatData } from './mitre_tactics_techniques';
-const { tactic, technique, subtechnique } = mockThreatData;
+const { tactic, technique, subtechnique } = getMockThreatData();
const { tactics, ...mockTechnique } = technique;
const { tactics: subtechniqueTactics, ...mockSubtechnique } = subtechnique;
diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts
index fb9661b509a33c..45cf7d725443d0 100644
--- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts
+++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/host_constants.ts
@@ -18,6 +18,7 @@ export const HOST_STATUS_TO_BADGE_COLOR = Object.freeze<
[HostStatus.UPDATING]: 'primary',
[HostStatus.OFFLINE]: 'default',
[HostStatus.INACTIVE]: 'default',
+ [HostStatus.UNENROLLED]: 'default',
});
export const POLICY_STATUS_TO_HEALTH_COLOR = Object.freeze<
diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_disabled_module.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_disabled_module.tsx
index 21a4beca72f3b2..1600356882c36b 100644
--- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_disabled_module.tsx
+++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_disabled_module.tsx
@@ -21,11 +21,11 @@ export const CtiDisabledModuleComponent = () => {
const danger = useMemo(
() => (
+
{i18n.DANGER_BUTTON}
}
diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_inner_panel.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_inner_panel.tsx
index 08bf0a432f9bb8..ddff78608dfb02 100644
--- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_inner_panel.tsx
+++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_inner_panel.tsx
@@ -17,13 +17,9 @@ const ButtonContainer = styled(EuiFlexGroup)`
padding: ${({ theme }) => theme.eui.paddingSizes.s};
`;
-const Title = styled(EuiText)<{ textcolor: 'primary' | 'warning' | 'danger' }>`
+const Title = styled(EuiText)<{ textcolor: 'primary' | 'warning' }>`
color: ${({ theme, textcolor }) =>
- textcolor === 'primary'
- ? theme.eui.euiColorPrimary
- : textcolor === 'warning'
- ? theme.eui.euiColorWarningText
- : theme.eui.euiColorDangerText};
+ textcolor === 'primary' ? theme.eui.euiColorPrimary : theme.eui.euiColorWarningText};
margin-bottom: ${({ theme }) => theme.eui.paddingSizes.m};
`;
@@ -40,12 +36,12 @@ export const CtiInnerPanel = ({
body,
button,
}: {
- color: 'primary' | 'warning' | 'danger';
+ color: 'primary' | 'warning';
title: string;
body: string;
button?: JSX.Element;
}) => {
- const iconType = color === 'primary' ? 'iInCircle' : color === 'warning' ? 'help' : 'alert';
+ const iconType = color === 'primary' ? 'iInCircle' : 'help';
return (
diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_no_events.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_no_events.test.tsx
index 5e1697279dd4c7..f00e1053e80822 100644
--- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_no_events.test.tsx
+++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_no_events.test.tsx
@@ -69,7 +69,7 @@ describe('CtiNoEvents', () => {
);
expect(wrapper.find('[data-test-subj="cti-total-event-count"]').text()).toEqual(
- 'Showing: 0 events'
+ 'Showing: 0 indicators'
);
});
});
diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_with_events.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_with_events.test.tsx
index 3b03b9c418a1cd..fac05bb72df38f 100644
--- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_with_events.test.tsx
+++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/cti_with_events.test.tsx
@@ -51,7 +51,7 @@ describe('CtiWithEvents', () => {
);
expect(wrapper.find('[data-test-subj="cti-total-event-count"]').text()).toEqual(
- `Showing: ${mockCtiWithEventsProps.totalCount} events`
+ `Showing: ${mockCtiWithEventsProps.totalCount} indicators`
);
});
});
diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.test.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.test.tsx
index 59ee1e5447ba30..f0e3bcaaec6e02 100644
--- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.test.tsx
+++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.test.tsx
@@ -141,7 +141,7 @@ describe('ThreatIntelPanelView', () => {
);
expect(wrapper.find('[data-test-subj="cti-total-event-count"]').text()).toEqual(
- `Showing: ${mockThreatIntelPanelViewProps.totalEventCount} events`
+ `Showing: ${mockThreatIntelPanelViewProps.totalEventCount} indicators`
);
});
});
diff --git a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx
index b34f6e657d39a9..babbd5d13224f1 100644
--- a/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx
+++ b/x-pack/plugins/security_solution/public/overview/components/overview_cti_links/threat_intel_panel_view.tsx
@@ -25,6 +25,7 @@ import { CtiListItem } from '../../containers/overview_cti_links/helpers';
import { useKibana } from '../../../common/lib/kibana';
import { CtiInnerPanel } from './cti_inner_panel';
import * as i18n from './translations';
+import { shortenCountIntoString } from '../../../common/utils/shorten_count_into_string';
const DashboardLink = styled.li`
margin: 0 ${({ theme }) => theme.eui.paddingSizes.s} 0 ${({ theme }) => theme.eui.paddingSizes.m};
@@ -84,7 +85,7 @@ export const ThreatIntelPanelView: React.FC = ({
() => (
@@ -159,10 +160,10 @@ export const ThreatIntelPanelView: React.FC = ({
alignItems="center"
justifyContent="flexEnd"
>
-
- {count}
+
+ {shortenCountIntoString(count)}
-
+
{path ? (
{linkCopy}
diff --git a/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/index.tsx b/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/index.tsx
index b7f919dc97013d..8839aff7dc33d2 100644
--- a/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/index.tsx
+++ b/x-pack/plugins/security_solution/public/overview/containers/overview_cti_links/index.tsx
@@ -74,8 +74,8 @@ export const useCtiDashboardLinks = (
})
)
);
- const items = DashboardsSO.savedObjects?.reduce(
- (acc: CtiListItem[], dashboardSO, i) => {
+ const items = DashboardsSO.savedObjects
+ ?.reduce((acc: CtiListItem[], dashboardSO, i) => {
const item = createLinkFromDashboardSO(
dashboardSO,
eventCountsByDataset,
@@ -87,9 +87,8 @@ export const useCtiDashboardLinks = (
acc.push(item);
}
return acc;
- },
- []
- );
+ }, [])
+ .sort((a, b) => (a.title > b.title ? 1 : -1));
setListItems(items);
} else {
handleDisabledPlugin();
diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx
index 2c88b305c7d05f..dac10f46487841 100644
--- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx
+++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/agent_statuses.tsx
@@ -6,11 +6,12 @@
*/
import React from 'react';
-import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiText } from '@elastic/eui';
import { DefaultDraggable } from '../../../../../common/components/draggables';
import { EndpointHostIsolationStatus } from '../../../../../common/components/endpoint/host_isolation';
import { useHostIsolationStatus } from '../../../../../detections/containers/detection_engine/alerts/use_host_isolation_status';
import { AgentStatus } from '../../../../../common/components/endpoint/agent_status';
+import { EMPTY_STATUS } from './translations';
export const AgentStatuses = React.memo(
({
@@ -33,16 +34,22 @@ export const AgentStatuses = React.memo(
const isolationFieldName = 'host.isolation';
return (
-
-
-
-
-
+ {agentStatus !== undefined ? (
+
+
+
+
+
+ ) : (
+
+ {EMPTY_STATUS}
+
+ )}
{
}
return this.getButton(
- }>
+ }>
,
(activeSpace as Space).name
diff --git a/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx b/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx
index 479a512b7238a1..9f00dd2e8f0619 100644
--- a/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx
+++ b/x-pack/plugins/uptime/public/components/common/header/action_menu_content.tsx
@@ -6,7 +6,7 @@
*/
import React from 'react';
-import { EuiButtonEmpty, EuiHeaderLinks, EuiHeaderSectionItem, EuiToolTip } from '@elastic/eui';
+import { EuiHeaderLinks, EuiToolTip, EuiHeaderLink } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import { useHistory } from 'react-router-dom';
@@ -51,53 +51,45 @@ export function ActionMenuContent(): React.ReactElement {
return (
-
-
+
+
+
+
+
+ {ANALYZE_MESSAGE}
}>
+
-
-
-
-
-
-
-
- {ANALYZE_MESSAGE}}>
-
- {ANALYZE_DATA}
-
-
-
-
-
- {ADD_DATA_LABEL}
-
-
+ {ANALYZE_DATA}
+
+
+
+
+ {ADD_DATA_LABEL}
+
);
}
diff --git a/x-pack/plugins/uptime/public/components/monitor/monitor_title.test.tsx b/x-pack/plugins/uptime/public/components/monitor/monitor_title.test.tsx
index 4fd6335c3d3ca9..726ad235f7f49e 100644
--- a/x-pack/plugins/uptime/public/components/monitor/monitor_title.test.tsx
+++ b/x-pack/plugins/uptime/public/components/monitor/monitor_title.test.tsx
@@ -11,7 +11,7 @@ import { screen } from '@testing-library/react';
import { render } from '../../lib/helper/rtl_helpers';
import * as reactRouterDom from 'react-router-dom';
import { Ping } from '../../../common/runtime_types';
-import { MonitorPageTitle } from './monitor_title';
+import { MonitorPageTitle, MonitorPageTitleContent } from './monitor_title';
jest.mock('react-router-dom', () => {
const originalModule = jest.requireActual('react-router-dom');
@@ -77,11 +77,17 @@ describe('MonitorTitle component', () => {
});
it('renders the monitor heading and EnableMonitorAlert toggle', () => {
- render(, {
- state: { monitorStatus: { status: monitorStatusWithName, loading: false } },
- });
- expect(screen.getByRole('heading', { level: 1, name: monitorName })).toBeInTheDocument();
- expect(screen.getByTestId('uptimeDisplayDefineConnector')).toBeInTheDocument();
+ render(
+ <>
+
+
+ >,
+ {
+ state: { monitorStatus: { status: monitorStatusWithName, loading: false } },
+ }
+ );
+ expect(screen.getByText(monitorName));
+ expect(screen.getByRole('switch')).toBeInTheDocument();
});
it('renders the user provided monitorId when the name is not present', () => {
@@ -89,21 +95,24 @@ describe('MonitorTitle component', () => {
render(, {
state: { monitorStatus: { status: defaultMonitorStatus, loading: false } },
});
- expect(screen.getByRole('heading', { level: 1, name: defaultMonitorId })).toBeInTheDocument();
+ expect(screen.getByText(defaultMonitorId));
});
it('renders the url when the monitorId is auto generated and the monitor name is not present', () => {
mockReactRouterDomHooks({ useParamsResponse: { monitorId: autoGeneratedMonitorIdEncoded } });
- render(, {
- state: { monitorStatus: { status: defaultMonitorStatus, loading: false } },
- });
- expect(
- screen.getByRole('heading', { level: 1, name: defaultMonitorStatus.url?.full })
- ).toBeInTheDocument();
+ render(
+
+
+
,
+ {
+ state: { monitorStatus: { status: defaultMonitorStatus, loading: false } },
+ }
+ );
+ expect(screen.getByText(defaultMonitorStatus!.url!.full!));
});
it('renders beta disclaimer for synthetics monitors', () => {
- render(, {
+ render(, {
state: { monitorStatus: { status: defaultBrowserMonitorStatus, loading: false } },
});
const betaLink = screen.getByRole('link', {
diff --git a/x-pack/plugins/uptime/public/components/monitor/monitor_title.tsx b/x-pack/plugins/uptime/public/components/monitor/monitor_title.tsx
index 2112af06536695..aa68e2aa7fc4bc 100644
--- a/x-pack/plugins/uptime/public/components/monitor/monitor_title.tsx
+++ b/x-pack/plugins/uptime/public/components/monitor/monitor_title.tsx
@@ -5,15 +5,7 @@
* 2.0.
*/
-import {
- EuiBadge,
- EuiFlexGroup,
- EuiFlexItem,
- EuiSpacer,
- EuiTitle,
- EuiLink,
- EuiText,
-} from '@elastic/eui';
+import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiLink, EuiText } from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n/react';
import React from 'react';
import { useSelector } from 'react-redux';
@@ -40,18 +32,11 @@ const getPageTitle = (monitorId: string, selectedMonitor: Ping | null) => {
return monitorId;
};
-export const MonitorPageTitle: React.FC = () => {
+export const MonitorPageTitleContent: React.FC = () => {
const monitorId = useMonitorId();
-
const selectedMonitor = useSelector(monitorStatusSelector);
-
- const nameOrId = selectedMonitor?.monitor?.name || getPageTitle(monitorId, selectedMonitor);
-
const type = selectedMonitor?.monitor?.type;
const isBrowser = type === 'browser';
-
- useBreadcrumbs([{ text: nameOrId }]);
-
const renderMonitorType = (monitorType: string) => {
switch (monitorType) {
case 'http':
@@ -86,12 +71,13 @@ export const MonitorPageTitle: React.FC = () => {
return '';
}
};
-
return (
<>
-
- {nameOrId}
-
+
+
+
+
+
@@ -118,7 +104,18 @@ export const MonitorPageTitle: React.FC = () => {
)}
-
>
);
};
+
+export const MonitorPageTitle: React.FC = () => {
+ const monitorId = useMonitorId();
+
+ const selectedMonitor = useSelector(monitorStatusSelector);
+
+ const nameOrId = selectedMonitor?.monitor?.name || getPageTitle(monitorId, selectedMonitor);
+
+ useBreadcrumbs([{ text: nameOrId }]);
+
+ return {nameOrId};
+};
diff --git a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/step_detail_container.tsx b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/step_detail_container.tsx
index 610107f406306a..c24ecd91838659 100644
--- a/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/step_detail_container.tsx
+++ b/x-pack/plugins/uptime/public/components/monitor/synthetics/step_detail/step_detail_container.tsx
@@ -16,7 +16,7 @@ import { useUiSetting$ } from '../../../../../../../../src/plugins/kibana_react/
import { useMonitorBreadcrumb } from './use_monitor_breadcrumb';
import { ClientPluginsStart } from '../../../../apps/plugin';
import { useKibana } from '../../../../../../../../src/plugins/kibana_react/public';
-import { StepPageTitle } from './step_page_title';
+import { StepPageTitleContent } from './step_page_title';
import { StepPageNavigation } from './step_page_nav';
import { WaterfallChartContainer } from './waterfall/waterfall_chart_container';
@@ -78,10 +78,11 @@ export const StepDetailContainer: React.FC = ({ checkGroup, stepIndex })
return (
void;
handleNextStep: () => void;
}
-export const StepPageTitle = ({
- stepName,
+
+export const StepPageTitleContent = ({
stepIndex,
totalSteps,
handleNextStep,
@@ -29,11 +29,6 @@ export const StepPageTitle = ({
}: Props) => {
return (
-
-
- {stepName}
-
-
diff --git a/x-pack/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx b/x-pack/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx
index 278958bd1987bb..22193fe4623d68 100644
--- a/x-pack/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx
+++ b/x-pack/plugins/uptime/public/components/overview/alerts/toggle_alert_flyout_button.tsx
@@ -6,7 +6,7 @@
*/
import {
- EuiButtonEmpty,
+ EuiHeaderLink,
EuiContextMenu,
EuiContextMenuPanelDescriptor,
EuiContextMenuPanelItemDescriptor,
@@ -123,8 +123,7 @@ export const ToggleAlertFlyoutButtonComponent: React.FC = ({
return (
= ({
id="xpack.uptime.alerts.toggleAlertFlyoutButtonText"
defaultMessage="Alerts and rules"
/>
-
+
}
closePopover={() => setIsOpen(false)}
isOpen={isOpen}
diff --git a/x-pack/plugins/uptime/public/components/overview/synthetics_callout.test.tsx b/x-pack/plugins/uptime/public/components/overview/synthetics_callout.test.tsx
index 5f6f9d7a7207ed..ec9e5f958ec3a5 100644
--- a/x-pack/plugins/uptime/public/components/overview/synthetics_callout.test.tsx
+++ b/x-pack/plugins/uptime/public/components/overview/synthetics_callout.test.tsx
@@ -67,9 +67,6 @@ describe('SyntheticsCallout', () => {
-
`);
});
@@ -128,9 +125,6 @@ describe('SyntheticsCallout', () => {
-
`);
wrapper.find('EuiButton').simulate('click');
diff --git a/x-pack/plugins/uptime/public/components/overview/synthetics_callout.tsx b/x-pack/plugins/uptime/public/components/overview/synthetics_callout.tsx
index fa28e42d7d0c14..4e9c3256f15781 100644
--- a/x-pack/plugins/uptime/public/components/overview/synthetics_callout.tsx
+++ b/x-pack/plugins/uptime/public/components/overview/synthetics_callout.tsx
@@ -5,14 +5,7 @@
* 2.0.
*/
-import {
- EuiButton,
- EuiButtonEmpty,
- EuiCallOut,
- EuiFlexGroup,
- EuiFlexItem,
- EuiSpacer,
-} from '@elastic/eui';
+import { EuiButton, EuiButtonEmpty, EuiCallOut, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React, { useState } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
@@ -74,7 +67,6 @@ export const SyntheticsCallout = () => {
-
>
);
};
diff --git a/x-pack/plugins/uptime/public/routes.tsx b/x-pack/plugins/uptime/public/routes.tsx
index e3c558cee2c320..2b0cc4dc5e5c2b 100644
--- a/x-pack/plugins/uptime/public/routes.tsx
+++ b/x-pack/plugins/uptime/public/routes.tsx
@@ -23,7 +23,7 @@ import { UptimePage, useUptimeTelemetry } from './hooks';
import { OverviewPageComponent } from './pages/overview';
import { SyntheticsCheckSteps } from './pages/synthetics/synthetics_checks';
import { ClientPluginsStart } from './apps/plugin';
-import { MonitorPageTitle } from './components/monitor/monitor_title';
+import { MonitorPageTitle, MonitorPageTitleContent } from './components/monitor/monitor_title';
import { UptimeDatePicker } from './components/common/uptime_date_picker';
import { useKibana } from '../../../../src/plugins/kibana_react/public';
import { CertRefreshBtn } from './components/certificates/cert_refresh_btn';
@@ -36,10 +36,16 @@ interface RouteProps {
dataTestSubj: string;
title: string;
telemetryId: UptimePage;
- pageHeader?: { pageTitle: string | JSX.Element; rightSideItems?: JSX.Element[] };
+ pageHeader?: {
+ children?: JSX.Element;
+ pageTitle: string | JSX.Element;
+ rightSideItems?: JSX.Element[];
+ };
}
-const baseTitle = 'Uptime - Kibana';
+const baseTitle = i18n.translate('xpack.uptime.routes.baseTitle', {
+ defaultMessage: 'Uptime - Kibana',
+});
export const MONITORING_OVERVIEW_LABEL = i18n.translate('xpack.uptime.overview.heading', {
defaultMessage: 'Monitors',
@@ -47,18 +53,25 @@ export const MONITORING_OVERVIEW_LABEL = i18n.translate('xpack.uptime.overview.h
const Routes: RouteProps[] = [
{
- title: `Monitor | ${baseTitle}`,
+ title: i18n.translate('xpack.uptime.monitorRoute.title', {
+ defaultMessage: 'Monitor | {baseTitle}',
+ values: { baseTitle },
+ }),
path: MONITOR_ROUTE,
component: MonitorPage,
dataTestSubj: 'uptimeMonitorPage',
telemetryId: UptimePage.Monitor,
pageHeader: {
+ children: ,
pageTitle: ,
rightSideItems: [],
},
},
{
- title: `Settings | ${baseTitle}`,
+ title: i18n.translate('xpack.uptime.settingsRoute.title', {
+ defaultMessage: `Settings | {baseTitle}`,
+ values: { baseTitle },
+ }),
path: SETTINGS_ROUTE,
component: SettingsPage,
dataTestSubj: 'uptimeSettingsPage',
@@ -70,7 +83,10 @@ const Routes: RouteProps[] = [
},
},
{
- title: `Certificates | ${baseTitle}`,
+ title: i18n.translate('xpack.uptime.certificatesRoute.title', {
+ defaultMessage: `Certificates | {baseTitle}`,
+ values: { baseTitle },
+ }),
path: CERTIFICATES_ROUTE,
component: CertificatesPage,
dataTestSubj: 'uptimeCertificatesPage',
@@ -81,7 +97,10 @@ const Routes: RouteProps[] = [
},
},
{
- title: baseTitle,
+ title: i18n.translate('xpack.uptime.stepDetailRoute.title', {
+ defaultMessage: 'Synthetics detail | {baseTitle}',
+ values: { baseTitle },
+ }),
path: STEP_DETAIL_ROUTE,
component: StepDetailPage,
dataTestSubj: 'uptimeStepDetailPage',
diff --git a/x-pack/plugins/uptime/server/lib/requests/get_certs.ts b/x-pack/plugins/uptime/server/lib/requests/get_certs.ts
index 1b20ed9085fefc..7639484f517374 100644
--- a/x-pack/plugins/uptime/server/lib/requests/get_certs.ts
+++ b/x-pack/plugins/uptime/server/lib/requests/get_certs.ts
@@ -138,7 +138,6 @@ export const getCerts: UMElasticsearchQueryFn = asyn
searchBody.query.bool.filter.push(validityFilters);
}
- // console.log(JSON.stringify(params, null, 2));
const { body: result } = await uptimeEsClient.search({
body: searchBody,
});
diff --git a/x-pack/test/load/runner.ts b/x-pack/test/load/runner.ts
index 2d379391b20897..0bea5992f55394 100644
--- a/x-pack/test/load/runner.ts
+++ b/x-pack/test/load/runner.ts
@@ -18,6 +18,7 @@ const simulationPackage = 'org.kibanaLoadTest.simulation';
const simulationFIleExtension = '.scala';
const gatlingProjectRootPath: string =
process.env.GATLING_PROJECT_PATH || resolve(REPO_ROOT, '../kibana-load-testing');
+const puppeteerProjectRootPath: string = resolve(gatlingProjectRootPath, 'puppeteer');
const simulationEntry: string = process.env.GATLING_SIMULATIONS || 'branch.DemoJourney';
if (!Fs.existsSync(gatlingProjectRootPath)) {
@@ -52,6 +53,15 @@ export async function GatlingTestRunner({ getService }: FtrProviderContext) {
const log = getService('log');
await withProcRunner(log, async (procs) => {
+ await procs.run('node build/index.js', {
+ cmd: 'node',
+ args: ['build/index.js'],
+ cwd: puppeteerProjectRootPath,
+ env: {
+ ...process.env,
+ },
+ wait: true,
+ });
for (let i = 0; i < simulationClasses.length; i++) {
await procs.run('gatling: test', {
cmd: 'mvn',
diff --git a/x-pack/test/stack_functional_integration/apps/ccs/ccs_discover.js b/x-pack/test/stack_functional_integration/apps/ccs/ccs_discover.js
index a22e4438c7dbdd..588ff9a6e9f928 100644
--- a/x-pack/test/stack_functional_integration/apps/ccs/ccs_discover.js
+++ b/x-pack/test/stack_functional_integration/apps/ccs/ccs_discover.js
@@ -5,16 +5,7 @@
* 2.0.
*/
-import fs from 'fs';
-import { resolve } from 'path';
import expect from '@kbn/expect';
-import { Client as EsClient } from '@elastic/elasticsearch';
-import { KbnClient } from '@kbn/test';
-import { EsArchiver } from '@kbn/es-archiver';
-import { CA_CERT_PATH, REPO_ROOT } from '@kbn/dev-utils';
-
-const INTEGRATION_TEST_ROOT = process.env.WORKSPACE || resolve(REPO_ROOT, '../integration-test');
-const ARCHIVE = resolve(INTEGRATION_TEST_ROOT, 'test/es_archives/metricbeat');
export default ({ getService, getPageObjects }) => {
describe('Cross cluster search test in discover', async () => {
@@ -212,151 +203,5 @@ export default ({ getService, getPageObjects }) => {
expect(hitCount).to.be.lessThan(originalHitCount);
});
});
-
- describe('Detection engine', async function () {
- const supertest = getService('supertest');
- const esSupertest = getService('esSupertest');
- const config = getService('config');
-
- const esClient = new EsClient({
- ssl: {
- ca: fs.readFileSync(CA_CERT_PATH, 'utf-8'),
- },
- nodes: [process.env.TEST_ES_URLDATA],
- requestTimeout: config.get('timeouts.esRequestTimeout'),
- });
-
- const kbnClient = new KbnClient({
- log,
- url: process.env.TEST_KIBANA_URLDATA,
- certificateAuthorities: config.get('servers.kibana.certificateAuthorities'),
- uiSettingDefaults: kibanaServer.uiSettings,
- });
-
- const esArchiver = new EsArchiver({
- log,
- client: esClient,
- kbnClient,
- });
-
- let signalsId;
- let dataId;
- let ruleId;
-
- before('Prepare .siem-signal-*', async function () {
- log.info('Create index');
- // visit app/security so to create .siem-signals-* as side effect
- await PageObjects.common.navigateToApp('security', { insertTimestamp: false });
-
- log.info('Create index pattern');
- signalsId = await supertest
- .post('/api/index_patterns/index_pattern')
- .set('kbn-xsrf', 'true')
- .send({
- index_pattern: {
- title: '.siem-signals-*',
- },
- override: true,
- })
- .expect(200)
- .then((res) => JSON.parse(res.text).index_pattern.id);
- log.debug('id: ' + signalsId);
- });
-
- before('Prepare data:metricbeat-*', async function () {
- log.info('Create index');
- await esArchiver.load(ARCHIVE);
-
- log.info('Create index pattern');
- dataId = await supertest
- .post('/api/index_patterns/index_pattern')
- .set('kbn-xsrf', 'true')
- .send({
- index_pattern: {
- title: 'data:metricbeat-*',
- },
- override: true,
- })
- .expect(200)
- .then((res) => JSON.parse(res.text).index_pattern.id);
- log.debug('id: ' + dataId);
- });
-
- before('Add detection rule', async function () {
- ruleId = await supertest
- .post('/api/detection_engine/rules')
- .set('kbn-xsrf', 'true')
- .send({
- description: 'This is the description of the rule',
- risk_score: 17,
- severity: 'low',
- interval: '10s',
- name: 'CCS_Detection_test',
- type: 'query',
- from: 'now-1y',
- index: ['data:metricbeat-*'],
- query: '*:*',
- language: 'kuery',
- enabled: true,
- })
- .expect(200)
- .then((res) => JSON.parse(res.text).id);
- log.debug('id: ' + ruleId);
- });
-
- after('Clean up detection rule', async function () {
- if (ruleId !== undefined) {
- log.debug('id: ' + ruleId);
- await supertest
- .delete('/api/detection_engine/rules?id=' + ruleId)
- .set('kbn-xsrf', 'true')
- .expect(200);
- }
- });
-
- after('Clean up data:metricbeat-*', async function () {
- if (dataId !== undefined) {
- log.info('Delete index pattern');
- log.debug('id: ' + dataId);
- await supertest
- .delete('/api/index_patterns/index_pattern/' + dataId)
- .set('kbn-xsrf', 'true')
- .expect(200);
- }
-
- log.info('Delete index');
- await esArchiver.unload(ARCHIVE);
- });
-
- after('Clean up .siem-signal-*', async function () {
- if (signalsId !== undefined) {
- log.info('Delete index pattern: .siem-signals-*');
- log.debug('id: ' + signalsId);
- await supertest
- .delete('/api/index_patterns/index_pattern/' + signalsId)
- .set('kbn-xsrf', 'true')
- .expect(200);
- }
-
- log.info('Delete index alias: .siem-signals-default');
- await esSupertest
- .delete('/.siem-signals-default-000001/_alias/.siem-signals-default')
- .expect(200);
-
- log.info('Delete index: .siem-signals-default-000001');
- await esSupertest.delete('/.siem-signals-default-000001').expect(200);
- });
-
- it('Should generate alerts based on remote events', async function () {
- log.info('Check if any alert got to .siem-signals-*');
- await PageObjects.common.navigateToApp('discover', { insertTimestamp: false });
- await PageObjects.discover.selectIndexPattern('.siem-signals-*');
- await retry.tryForTime(30000, async () => {
- const hitCount = await PageObjects.discover.getHitCount();
- log.debug('### hit count = ' + hitCount);
- expect(hitCount).to.be('100');
- });
- });
- });
});
};
diff --git a/x-pack/test/stack_functional_integration/apps/monitoring/_monitoring_metricbeat.js b/x-pack/test/stack_functional_integration/apps/monitoring/_monitoring_metricbeat.js
index d8341c56aa25cc..9dcc18b3c3f203 100644
--- a/x-pack/test/stack_functional_integration/apps/monitoring/_monitoring_metricbeat.js
+++ b/x-pack/test/stack_functional_integration/apps/monitoring/_monitoring_metricbeat.js
@@ -12,6 +12,7 @@ export default ({ getService, getPageObjects }) => {
const log = getService('log');
const testSubjects = getService('testSubjects');
const isSaml = !!process.env.VM.includes('saml') || !!process.env.VM.includes('oidc');
+ const clusterOverview = getService('monitoringClusterOverview');
before(async () => {
await browser.setWindowSize(1200, 800);
@@ -25,6 +26,7 @@ export default ({ getService, getPageObjects }) => {
}
// navigateToApp without a username and password will default to the superuser
await PageObjects.common.navigateToApp('monitoring', { insertTimestamp: false });
+ await clusterOverview.closeAlertsModal();
});
it('should have Monitoring already enabled', async () => {
diff --git a/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts b/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts
index 73819b5bac695c..0bc3cd7c2610eb 100644
--- a/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts
+++ b/x-pack/test/upgrade/apps/dashboard/dashboard_smoke_tests.ts
@@ -16,6 +16,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
const renderable = getService('renderable');
const dashboardExpect = getService('dashboardExpect');
const PageObjects = getPageObjects(['common', 'header', 'home', 'dashboard', 'timePicker']);
+ const kibanaServer = getService('kibanaServer');
+ const browser = getService('browser');
describe('dashboard smoke tests', function describeIndexTests() {
const spaces = [
@@ -36,6 +38,14 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
basePath,
});
await PageObjects.header.waitUntilLoadingHasFinished();
+ await kibanaServer.uiSettings.update(
+ {
+ 'visualization:visualize:legacyChartsLibrary': true,
+ 'visualization:visualize:legacyPieChartsLibrary': true,
+ },
+ { space }
+ );
+ await browser.refresh();
});
dashboardTests.forEach(({ name, numPanels }) => {
it('should launch sample ' + name + ' data set dashboard', async () => {
@@ -56,9 +66,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await renderable.waitForRender();
log.debug('Checking pie charts rendered');
await pieChart.expectPieSliceCount(4);
- // https://github.com/elastic/kibana/issues/92887
- // log.debug('Checking area, bar and heatmap charts rendered');
- // await dashboardExpect.seriesElementCount(15);
+ log.debug('Checking area, bar and heatmap charts rendered');
+ await dashboardExpect.seriesElementCount(15);
log.debug('Checking saved searches rendered');
await dashboardExpect.savedSearchRowCount(49);
log.debug('Checking input controls rendered');
diff --git a/x-pack/test/upgrade/apps/reporting/reporting_smoke_tests.ts b/x-pack/test/upgrade/apps/reporting/reporting_smoke_tests.ts
index c00e761d54226a..20fc34f77dbf80 100644
--- a/x-pack/test/upgrade/apps/reporting/reporting_smoke_tests.ts
+++ b/x-pack/test/upgrade/apps/reporting/reporting_smoke_tests.ts
@@ -69,6 +69,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
if (type === 'pdf_optimize') {
await testSubjects.click('usePrintLayout');
}
+ const advOpt = await find.byXPath(`//button[descendant::*[text()='Advanced options']]`);
+ await advOpt.click();
const postUrl = await find.byXPath(`//button[descendant::*[text()='Copy POST URL']]`);
await postUrl.click();
const url = await browser.getClipboardValue();
diff --git a/yarn.lock b/yarn.lock
index dccbd8f91a4299..7a70953379f54e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1389,10 +1389,10 @@
dependencies:
object-hash "^1.3.0"
-"@elastic/charts@31.1.0":
- version "31.1.0"
- resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-31.1.0.tgz#cebfd45e672ab19d7d6c5a7f7e3115a6eaa41e8f"
- integrity sha512-D2zPT7CRweRdbfhO9gd1+YBm0ETdJsEkh+Su0I6tleINqKKuSB+kPOG6t+fm0+HsR72pX4dKvT60ikZJZ3fRhg==
+"@elastic/charts@32.0.0":
+ version "32.0.0"
+ resolved "https://registry.yarnpkg.com/@elastic/charts/-/charts-32.0.0.tgz#f747b8fa931027ba7476a6284be03383cd6a6dab"
+ integrity sha512-3cvX0Clezocd6/T2R5h3+nilPdIgWrO+it043giyW5U0pAtFC5P+5VyNEjn22LlD3zzbndxAbXHSj0QDvHXOBw==
dependencies:
"@popperjs/core" "^2.4.0"
chroma-js "^2.1.0"