From e628ae5b54fcaf240415864a1de3fda4b4b82f75 Mon Sep 17 00:00:00 2001 From: Katerina Patticha Date: Tue, 29 Mar 2022 09:46:14 +0200 Subject: [PATCH 01/31] [APM] Add loading state for trace samples (#128268) * Add loading state for trace samples * Fix message when there are no traces * Remove unused status * Use traces samples status to display loading indicator * Clean up code * Fix tests --- .../distribution/index.test.tsx | 2 + .../distribution/index.tsx | 8 +- .../transaction_details/trace_samples_tab.tsx | 2 + .../transaction_details_tabs.tsx | 12 +- .../app/transaction_details/types.ts | 2 + .../waterfall_with_summary/index.tsx | 72 ++++++----- .../maybe_view_trace_link.tsx | 114 ++++++++++-------- .../waterfall/transaction_flyout/index.tsx | 5 +- .../custom_link_list.tsx | 4 +- .../custom_link_menu_section/index.tsx | 2 +- .../transaction_action_menu/sections.ts | 3 +- .../transaction_action_menu.test.tsx | 7 +- .../transaction_action_menu.tsx | 108 ++++++++++------- 13 files changed, 197 insertions(+), 144 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx index 1e4d1816bf84a..e2530458ae980 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.test.tsx @@ -100,6 +100,7 @@ describe('transaction_details/distribution', () => { onChartSelection={jest.fn()} onClearSelection={jest.fn()} traceSamples={[]} + traceSamplesStatus={useFetcherModule.FETCH_STATUS.LOADING} />, { wrapper: Wrapper } @@ -124,6 +125,7 @@ describe('transaction_details/distribution', () => { onChartSelection={jest.fn()} onClearSelection={jest.fn()} traceSamples={[]} + traceSamplesStatus={useFetcherModule.FETCH_STATUS.SUCCESS} /> ); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx index 7d387a39f9334..ca2a3584c8942 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/distribution/index.tsx @@ -59,6 +59,7 @@ interface TransactionDistributionProps { onClearSelection: () => void; selection?: Selection; traceSamples: TabContentProps['traceSamples']; + traceSamplesStatus: FETCH_STATUS; } export function TransactionDistribution({ @@ -66,10 +67,15 @@ export function TransactionDistribution({ onClearSelection, selection, traceSamples, + traceSamplesStatus, }: TransactionDistributionProps) { const { urlParams } = useLegacyUrlParams(); const { waterfall, status: waterfallStatus } = useWaterfallFetcher(); + const isLoading = + waterfallStatus === FETCH_STATUS.LOADING || + traceSamplesStatus === FETCH_STATUS.LOADING; + const markerCurrentTransaction = waterfall.entryWaterfallTransaction?.doc.transaction.duration.us; @@ -189,7 +195,7 @@ export function TransactionDistribution({ diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/trace_samples_tab.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/trace_samples_tab.tsx index ad629b7a2d132..d83211a72ea59 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/trace_samples_tab.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/trace_samples_tab.tsx @@ -18,6 +18,7 @@ function TraceSamplesTab({ sampleRangeFrom, sampleRangeTo, traceSamples, + traceSamplesStatus, }: TabContentProps) { return ( ); diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx index 5e9f1f8149d9d..b0b5d495d1f8e 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/transaction_details_tabs.tsx @@ -41,11 +41,12 @@ export function TransactionDetailsTabs() { tabs.find((tab) => tab.key === currentTab) ?? traceSamplesTab; const { environment, kuery, transactionName } = query; - const { traceSamplesData } = useTransactionTraceSamplesFetcher({ - transactionName, - kuery, - environment, - }); + const { traceSamplesData, traceSamplesStatus } = + useTransactionTraceSamplesFetcher({ + transactionName, + kuery, + environment, + }); const selectSampleFromChartSelection = (selection: XYBrushEvent) => { if (selection !== undefined) { @@ -139,6 +140,7 @@ export function TransactionDetailsTabs() { sampleRangeTo, selectSampleFromChartSelection, traceSamples, + traceSamplesStatus, }} /> diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/types.ts b/x-pack/plugins/apm/public/components/app/transaction_details/types.ts index c3d2b9648e82a..2014f7588293d 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/types.ts +++ b/x-pack/plugins/apm/public/components/app/transaction_details/types.ts @@ -8,6 +8,7 @@ import { XYBrushEvent } from '@elastic/charts'; import type { TraceSample } from '../../../hooks/use_transaction_trace_samples_fetcher'; +import { FETCH_STATUS } from '../../../hooks/use_fetcher'; export interface TabContentProps { clearChartSelection: () => void; @@ -16,4 +17,5 @@ export interface TabContentProps { sampleRangeTo?: number; selectSampleFromChartSelection: (selection: XYBrushEvent) => void; traceSamples: TraceSample[]; + traceSamplesStatus: FETCH_STATUS; } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx index f528ce17c02f0..93913aff6cb6b 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/index.tsx @@ -65,10 +65,9 @@ export function WaterfallWithSummary({ }; const { entryWaterfallTransaction } = waterfall; - if (!entryWaterfallTransaction) { - const content = isLoading ? ( - - ) : ( + + if ((!entryWaterfallTransaction || traceSamples.length === 0) && !isLoading) { + return ( @@ -80,11 +79,9 @@ export function WaterfallWithSummary({ titleSize="s" /> ); - - return content; } - const entryTransaction = entryWaterfallTransaction.doc; + const entryTransaction = entryWaterfallTransaction?.doc; return ( <> @@ -99,43 +96,52 @@ export function WaterfallWithSummary({ - {traceSamples && ( - - )} + - + + + + - - - - - + {isLoading || !entryTransaction ? ( + + ) : ( + <> + + + + + )} ); } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/maybe_view_trace_link.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/maybe_view_trace_link.tsx index 90fdaddc71408..ecb9fb9a3bc39 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/maybe_view_trace_link.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/maybe_view_trace_link.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiButton, EuiFlexItem, EuiToolTip } from '@elastic/eui'; +import { EuiButton, EuiToolTip } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; import { getNextEnvironmentUrlParam } from '../../../../../common/environment_filter_values'; @@ -15,12 +15,35 @@ import { IWaterfall } from './waterfall_container/waterfall/waterfall_helpers/wa import { Environment } from '../../../../../common/environment_rt'; import { useApmParams } from '../../../../hooks/use_apm_params'; +function FullTraceButton({ + isLoading, + isDisabled, +}: { + isLoading?: boolean; + isDisabled?: boolean; +}) { + return ( + + {i18n.translate('xpack.apm.transactionDetails.viewFullTraceButtonLabel', { + defaultMessage: 'View full trace', + })} + + ); +} + export function MaybeViewTraceLink({ + isLoading, transaction, waterfall, environment, }: { - transaction: ITransaction; + isLoading: boolean; + transaction?: ITransaction; waterfall: IWaterfall; environment: Environment; }) { @@ -28,31 +51,24 @@ export function MaybeViewTraceLink({ query: { latencyAggregationType, comparisonEnabled, offset }, } = useApmParams('/services/{serviceName}/transactions/view'); - const viewFullTraceButtonLabel = i18n.translate( - 'xpack.apm.transactionDetails.viewFullTraceButtonLabel', - { - defaultMessage: 'View full trace', - } - ); + if (isLoading || !transaction) { + return ; + } const { rootTransaction } = waterfall; // the traceroot cannot be found, so we cannot link to it if (!rootTransaction) { return ( - - - - {viewFullTraceButtonLabel} - - - + + + ); } @@ -61,20 +77,16 @@ export function MaybeViewTraceLink({ // the user is already viewing the full trace, so don't link to it if (isRoot) { return ( - - - - {viewFullTraceButtonLabel} - - - + + + ); // the user is viewing a zoomed in version of the trace. Link to the full trace @@ -85,23 +97,19 @@ export function MaybeViewTraceLink({ }); return ( - - - - {viewFullTraceButtonLabel} - - - + + + ); } } diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/transaction_flyout/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/transaction_flyout/index.tsx index 43a7ebfa2f97f..fd68fde81fb60 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/transaction_flyout/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/transaction_flyout/index.tsx @@ -76,7 +76,10 @@ export function TransactionFlyout({ - + diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/custom_link_menu_section/custom_link_list.tsx b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/custom_link_menu_section/custom_link_list.tsx index 7ea7cd35c443a..5cd7188c8ba8b 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/custom_link_menu_section/custom_link_list.tsx +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/custom_link_menu_section/custom_link_list.tsx @@ -20,7 +20,7 @@ export function CustomLinkList({ transaction, }: { customLinks: CustomLink[]; - transaction: Transaction; + transaction?: Transaction; }) { return ( @@ -39,7 +39,7 @@ export function CustomLinkList({ ); } -function getHref(link: CustomLink, transaction: Transaction) { +function getHref(link: CustomLink, transaction?: Transaction) { try { return Mustache.render(link.url, transaction); } catch (e) { diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/custom_link_menu_section/index.tsx b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/custom_link_menu_section/index.tsx index aa3445d098c0e..68442ede98347 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/custom_link_menu_section/index.tsx +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/custom_link_menu_section/index.tsx @@ -41,7 +41,7 @@ const DEFAULT_LINKS_TO_SHOW = 3; export function CustomLinkMenuSection({ transaction, }: { - transaction: Transaction; + transaction?: Transaction; }) { const [showAllLinks, setShowAllLinks] = useState(false); const [isCreateEditFlyoutOpen, setIsCreateEditFlyoutOpen] = useState(false); diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts index 20c10b6d9557c..8fbf0ea1f3235 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/sections.ts @@ -35,11 +35,12 @@ export const getSections = ({ location, urlParams, }: { - transaction: Transaction; + transaction?: Transaction; basePath: IBasePath; location: Location; urlParams: ApmUrlParams; }) => { + if (!transaction) return []; const hostName = transaction.host?.hostname; const podId = transaction.kubernetes?.pod?.uid; const containerId = transaction.container?.id; diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx index f2919fc12cad6..ebdbf759bcddc 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.test.tsx @@ -47,7 +47,10 @@ function Wrapper({ children }: { children?: React.ReactNode }) { const renderTransaction = async (transaction: Record) => { const rendered = render( - , + , { wrapper: Wrapper, } @@ -271,6 +274,7 @@ describe('TransactionActionMenu component', () => { return render( , @@ -308,6 +312,7 @@ describe('TransactionActionMenu component', () => { const component = render( , diff --git a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.tsx b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.tsx index 2f856dce387bf..253c792246139 100644 --- a/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.tsx +++ b/x-pack/plugins/apm/public/components/shared/transaction_action_menu/transaction_action_menu.tsx @@ -26,12 +26,24 @@ import { CustomLinkMenuSection } from './custom_link_menu_section'; import { getSections } from './sections'; interface Props { - readonly transaction: Transaction; + readonly transaction?: Transaction; + isLoading: boolean; } -function ActionMenuButton({ onClick }: { onClick: () => void }) { +function ActionMenuButton({ + onClick, + isLoading, +}: { + onClick: () => void; + isLoading: boolean; +}) { return ( - + {i18n.translate('xpack.apm.transactionActionMenu.actionsButtonLabel', { defaultMessage: 'Investigate', })} @@ -39,23 +51,12 @@ function ActionMenuButton({ onClick }: { onClick: () => void }) { ); } -export function TransactionActionMenu({ transaction }: Props) { +export function TransactionActionMenu({ transaction, isLoading }: Props) { const license = useLicenseContext(); const hasGoldLicense = license?.isActive && license?.hasAtLeast('gold'); - const { core } = useApmPluginContext(); - const location = useLocation(); - const { urlParams } = useLegacyUrlParams(); - const [isActionPopoverOpen, setIsActionPopoverOpen] = useState(false); - const sections = getSections({ - transaction, - basePath: core.http.basePath, - location, - urlParams, - }); - return ( <> setIsActionPopoverOpen( (prevIsActionPopoverOpen) => !prevIsActionPopoverOpen @@ -73,38 +75,52 @@ export function TransactionActionMenu({ transaction }: Props) { /> } > -
- {sections.map((section, idx) => { - const isLastSection = idx !== sections.length - 1; - return ( -
- {section.map((item) => ( -
- {item.title && {item.title}} - {item.subtitle && ( - {item.subtitle} - )} - - {item.actions.map((action) => ( - - ))} - -
- ))} - {isLastSection && } -
- ); - })} - - {hasGoldLicense && ( - - )} -
+ + {hasGoldLicense && }
); } + +function ActionMenuSections({ transaction }: { transaction?: Transaction }) { + const { core } = useApmPluginContext(); + const location = useLocation(); + const { urlParams } = useLegacyUrlParams(); + + const sections = getSections({ + transaction, + basePath: core.http.basePath, + location, + urlParams, + }); + + return ( +
+ {sections.map((section, idx) => { + const isLastSection = idx !== sections.length - 1; + return ( +
+ {section.map((item) => ( +
+ {item.title && {item.title}} + {item.subtitle && ( + {item.subtitle} + )} + + {item.actions.map((action) => ( + + ))} + +
+ ))} + {isLastSection && } +
+ ); + })} +
+ ); +} From 52f0bf0a6ab8df5d393630571b7c95535723f770 Mon Sep 17 00:00:00 2001 From: Giorgos Bamparopoulos Date: Tue, 29 Mar 2022 09:16:00 +0100 Subject: [PATCH 02/31] Set metadata tab as default and display Stack Trace tab only if stackframes exist (#128598) --- .../waterfall/span_flyout/index.tsx | 41 +++++++++++-------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx index 477098aa81d04..5d3c1d733e040 100644 --- a/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx +++ b/x-pack/plugins/apm/public/components/app/transaction_details/waterfall_with_summary/waterfall_container/waterfall/span_flyout/index.tsx @@ -21,6 +21,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React, { Fragment } from 'react'; +import { isEmpty } from 'lodash'; import { CompositeSpanDurationSummaryItem } from '../../../../../../shared/summary/composite_span_duration_summary_item'; import { euiStyled } from '../../../../../../../../../../../src/plugins/kibana_react/common'; import { Span } from '../../../../../../../../typings/es_schemas/ui/span'; @@ -216,24 +217,6 @@ export function SpanFlyout({ - - - - ), - }, { id: 'metadata', name: i18n.translate( @@ -249,6 +232,28 @@ export function SpanFlyout({ ), }, + ...(!isEmpty(stackframes) + ? [ + { + id: 'stack-trace', + name: i18n.translate( + 'xpack.apm.transactionDetails.spanFlyout.stackTraceTabLabel', + { + defaultMessage: 'Stack Trace', + } + ), + content: ( + + + + + ), + }, + ] + : []), ]} /> From eb51ea64c5bb531658c38e9995f7455c39822b63 Mon Sep 17 00:00:00 2001 From: Dmitrii Shevchenko Date: Tue, 29 Mar 2022 10:18:33 +0200 Subject: [PATCH 03/31] Add the ability to filter by index pattern to the rules management table (#128245) --- .../detection_rules/sorting.spec.ts | 14 ++-- .../cypress/tasks/alerts_detection_rules.ts | 2 +- .../filters/toggle_selected_group.tsx | 4 +- .../rule_actions_overflow/index.test.tsx | 6 +- .../detection_engine/rules/api.test.ts | 38 ++++++++- .../detection_engine/rules/utils.test.ts | 16 +++- .../detection_engine/rules/utils.ts | 64 +++++++++------ .../detection_engine/rules/all/actions.ts | 19 ----- .../all/bulk_actions/use_bulk_actions.tsx | 23 +++--- .../all/rules_table/rules_table_context.tsx | 27 +++--- .../rules/all/rules_table/use_find_rules.ts | 8 +- .../rules/all/rules_table/utils.ts | 32 +------- .../rules_table_filters.test.tsx | 77 ++++++----------- .../rules_table_filters.tsx | 82 +++++++------------ .../tags_filter_popover.test.tsx | 8 +- .../tags_filter_popover.tsx | 20 +---- .../rules/all/rules_tables.tsx | 62 +++++--------- .../rules/all/utility_bar.tsx | 15 +++- .../detection_engine/rules/translations.ts | 9 +- .../translations/translations/fr-FR.json | 2 - .../translations/translations/ja-JP.json | 2 - .../translations/translations/zh-CN.json | 2 - 22 files changed, 225 insertions(+), 307 deletions(-) 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 a162ca4a544d1..7084ff99b5881 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 @@ -13,7 +13,7 @@ import { FOURTH_RULE, RULES_TABLE, pageSelector, - RULES_TABLE_REFRESH_INDICATOR, + RULES_ROW, } from '../../screens/alerts_detection_rules'; import { goToManageAlertsDetectionRules, waitForAlertsPanelToBeLoaded } from '../../tasks/alerts'; @@ -90,14 +90,10 @@ describe('Alerts detection rules', () => { .invoke('text') .then((ruleNameFirstPage) => { goToPage(2); - cy.get(RULES_TABLE_REFRESH_INDICATOR).should('not.exist'); - cy.get(RULES_TABLE) - .find(RULE_NAME) - .first() - .invoke('text') - .should((ruleNameSecondPage) => { - expect(ruleNameFirstPage).not.to.eq(ruleNameSecondPage); - }); + // Check that the rules table shows at least one row + cy.get(RULES_TABLE).find(RULES_ROW).should('have.length.gte', 1); + // Check that the rules table doesn't show the rule from the first page + cy.get(RULES_TABLE).should('not.contain', ruleNameFirstPage); }); cy.get(RULES_TABLE) diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts index 8d125c242be35..afe3981219217 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts_detection_rules.ts @@ -154,7 +154,7 @@ export const goToRuleDetails = () => { }; export const goToTheRuleDetailsOf = (ruleName: string) => { - cy.get(RULE_NAME).contains(ruleName).click(); + cy.get(RULE_NAME).should('contain', ruleName).contains(ruleName).click(); }; export const loadPrebuiltDetectionRules = () => { diff --git a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/filters/toggle_selected_group.tsx b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/filters/toggle_selected_group.tsx index d452aa9a311e7..4f7064afe642f 100644 --- a/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/filters/toggle_selected_group.tsx +++ b/x-pack/plugins/security_solution/public/common/components/ml_popover/jobs_table/filters/toggle_selected_group.tsx @@ -5,12 +5,10 @@ * 2.0. */ -import { Dispatch, SetStateAction } from 'react'; - export const toggleSelectedGroup = ( group: string, selectedGroups: string[], - setSelectedGroups: Dispatch> + setSelectedGroups: (groups: string[]) => void ): void => { const selectedGroupIndex = selectedGroups.indexOf(group); const updatedSelectedGroups = [...selectedGroups]; diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_actions_overflow/index.test.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_actions_overflow/index.test.tsx index 3037a3c82f946..71fabef22c904 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_actions_overflow/index.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_actions_overflow/index.test.tsx @@ -178,7 +178,7 @@ describe('RuleActionsOverflow', () => { ).toEqual(false); }); - test('it calls duplicateRulesAction when rules-details-duplicate-rule is clicked', () => { + test('it calls duplicate action when rules-details-duplicate-rule is clicked', () => { const wrapper = mount( { ); }); - test('it calls duplicateRulesAction with the rule and rule.id when rules-details-duplicate-rule is clicked', () => { + test('it calls duplicate action with the rule and rule.id when rules-details-duplicate-rule is clicked', () => { const rule = mockRule('id'); const wrapper = mount( @@ -210,7 +210,7 @@ describe('RuleActionsOverflow', () => { }); }); - test('it calls editRuleAction after the rule is duplicated', async () => { + test('it navigates to edit page after the rule is duplicated', async () => { const rule = mockRule('id'); const ruleDuplicate = mockRule('newRule'); executeRulesBulkActionMock.mockImplementation(() => diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts index 16613d7cb4d0f..c8d8b5bb6ffd0 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/api.test.ts @@ -142,7 +142,37 @@ describe('Detections Rules API', () => { expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules/_find', { method: 'GET', query: { - filter: 'alert.attributes.name: hello world', + filter: + '(alert.attributes.name: "hello world" OR alert.attributes.params.index: "hello world" OR alert.attributes.params.threat.tactic.id: "hello world" OR alert.attributes.params.threat.tactic.name: "hello world" OR alert.attributes.params.threat.technique.id: "hello world" OR alert.attributes.params.threat.technique.name: "hello world")', + page: 1, + per_page: 20, + sort_field: 'enabled', + sort_order: 'desc', + }, + signal: abortCtrl.signal, + }); + }); + + test('check parameter url, query with a filter get escaped correctly', async () => { + await fetchRules({ + filterOptions: { + filter: '" OR (foo:bar)', + showCustomRules: false, + showElasticRules: false, + tags: [], + }, + sortingOptions: { + field: 'enabled', + order: 'desc', + }, + signal: abortCtrl.signal, + }); + + expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules/_find', { + method: 'GET', + query: { + filter: + '(alert.attributes.name: "\\" OR (foo:bar)" OR alert.attributes.params.index: "\\" OR (foo:bar)" OR alert.attributes.params.threat.tactic.id: "\\" OR (foo:bar)" OR alert.attributes.params.threat.tactic.name: "\\" OR (foo:bar)" OR alert.attributes.params.threat.technique.id: "\\" OR (foo:bar)" OR alert.attributes.params.threat.technique.name: "\\" OR (foo:bar)")', page: 1, per_page: 20, sort_field: 'enabled', @@ -226,7 +256,7 @@ describe('Detections Rules API', () => { expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules/_find', { method: 'GET', query: { - filter: 'alert.attributes.tags: "hello" AND alert.attributes.tags: "world"', + filter: 'alert.attributes.tags:("hello" AND "world")', page: 1, per_page: 20, sort_field: 'enabled', @@ -254,7 +284,7 @@ describe('Detections Rules API', () => { expect(fetchMock).toHaveBeenCalledWith('/api/detection_engine/rules/_find', { method: 'GET', query: { - filter: 'alert.attributes.tags: "hello" AND alert.attributes.tags: "world"', + filter: 'alert.attributes.tags:("hello" AND "world")', page: 1, per_page: 20, sort_field: 'updatedAt', @@ -353,7 +383,7 @@ describe('Detections Rules API', () => { method: 'GET', query: { filter: - 'alert.attributes.name: ruleName AND alert.attributes.tags: "__internal_immutable:false" AND alert.attributes.tags: "__internal_immutable:true" AND (alert.attributes.tags: "hello" AND alert.attributes.tags: "world")', + 'alert.attributes.tags: "__internal_immutable:false" AND alert.attributes.tags: "__internal_immutable:true" AND alert.attributes.tags:("hello" AND "world") AND (alert.attributes.name: "ruleName" OR alert.attributes.params.index: "ruleName" OR alert.attributes.params.threat.tactic.id: "ruleName" OR alert.attributes.params.threat.tactic.name: "ruleName" OR alert.attributes.params.threat.technique.id: "ruleName" OR alert.attributes.params.threat.technique.name: "ruleName")', page: 1, per_page: 20, sort_field: 'enabled', diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/utils.test.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/utils.test.ts index 7f69d07e83467..e3d2300972a51 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/utils.test.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/utils.test.ts @@ -26,7 +26,17 @@ describe('convertRulesFilterToKQL', () => { it('handles presence of "filter" properly', () => { const kql = convertRulesFilterToKQL({ ...filterOptions, filter: 'foo' }); - expect(kql).toBe('alert.attributes.name: foo'); + expect(kql).toBe( + '(alert.attributes.name: "foo" OR alert.attributes.params.index: "foo" OR alert.attributes.params.threat.tactic.id: "foo" OR alert.attributes.params.threat.tactic.name: "foo" OR alert.attributes.params.threat.technique.id: "foo" OR alert.attributes.params.threat.technique.name: "foo")' + ); + }); + + it('escapes "filter" value properly', () => { + const kql = convertRulesFilterToKQL({ ...filterOptions, filter: '" OR (foo: bar)' }); + + expect(kql).toBe( + '(alert.attributes.name: "\\" OR (foo: bar)" OR alert.attributes.params.index: "\\" OR (foo: bar)" OR alert.attributes.params.threat.tactic.id: "\\" OR (foo: bar)" OR alert.attributes.params.threat.tactic.name: "\\" OR (foo: bar)" OR alert.attributes.params.threat.technique.id: "\\" OR (foo: bar)" OR alert.attributes.params.threat.technique.name: "\\" OR (foo: bar)")' + ); }); it('handles presence of "showCustomRules" properly', () => { @@ -44,7 +54,7 @@ describe('convertRulesFilterToKQL', () => { it('handles presence of "tags" properly', () => { const kql = convertRulesFilterToKQL({ ...filterOptions, tags: ['tag1', 'tag2'] }); - expect(kql).toBe('alert.attributes.tags: "tag1" AND alert.attributes.tags: "tag2"'); + expect(kql).toBe('alert.attributes.tags:("tag1" AND "tag2")'); }); it('handles combination of different properties properly', () => { @@ -56,7 +66,7 @@ describe('convertRulesFilterToKQL', () => { }); expect(kql).toBe( - `alert.attributes.name: foo AND alert.attributes.tags: "${INTERNAL_IMMUTABLE_KEY}:true" AND (alert.attributes.tags: "tag1" AND alert.attributes.tags: "tag2")` + `alert.attributes.tags: "${INTERNAL_IMMUTABLE_KEY}:true" AND alert.attributes.tags:(\"tag1\" AND \"tag2\") AND (alert.attributes.name: \"foo\" OR alert.attributes.params.index: \"foo\" OR alert.attributes.params.threat.tactic.id: \"foo\" OR alert.attributes.params.threat.tactic.name: \"foo\" OR alert.attributes.params.threat.technique.id: \"foo\" OR alert.attributes.params.threat.technique.name: \"foo\")` ); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/utils.ts b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/utils.ts index 841b2adca09e0..f5e52fd6362c1 100644 --- a/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/utils.ts +++ b/x-pack/plugins/security_solution/public/detections/containers/detection_engine/rules/utils.ts @@ -6,8 +6,18 @@ */ import { INTERNAL_IMMUTABLE_KEY } from '../../../../../common/constants'; +import { escapeKuery } from '../../../../common/lib/keury'; import { FilterOptions } from './types'; +const SEARCHABLE_RULE_PARAMS = [ + 'alert.attributes.name', + 'alert.attributes.params.index', + 'alert.attributes.params.threat.tactic.id', + 'alert.attributes.params.threat.tactic.name', + 'alert.attributes.params.threat.technique.id', + 'alert.attributes.params.threat.technique.name', +]; + /** * Convert rules filter options object to KQL query * @@ -15,27 +25,35 @@ import { FilterOptions } from './types'; * * @returns KQL string */ -export const convertRulesFilterToKQL = (filterOptions: FilterOptions): string => { - const showCustomRuleFilter = filterOptions.showCustomRules - ? [`alert.attributes.tags: "${INTERNAL_IMMUTABLE_KEY}:false"`] - : []; - const showElasticRuleFilter = filterOptions.showElasticRules - ? [`alert.attributes.tags: "${INTERNAL_IMMUTABLE_KEY}:true"`] - : []; - const filtersWithoutTags = [ - ...(filterOptions.filter.length ? [`alert.attributes.name: ${filterOptions.filter}`] : []), - ...showCustomRuleFilter, - ...showElasticRuleFilter, - ].join(' AND '); - - const tags = filterOptions.tags - .map((t) => `alert.attributes.tags: "${t.replace(/"/g, '\\"')}"`) - .join(' AND '); - - const filterString = - filtersWithoutTags !== '' && tags !== '' - ? `${filtersWithoutTags} AND (${tags})` - : filtersWithoutTags + tags; - - return filterString; +export const convertRulesFilterToKQL = ({ + showCustomRules, + showElasticRules, + filter, + tags, +}: FilterOptions): string => { + const filters: string[] = []; + + if (showCustomRules) { + filters.push(`alert.attributes.tags: "${INTERNAL_IMMUTABLE_KEY}:false"`); + } + + if (showElasticRules) { + filters.push(`alert.attributes.tags: "${INTERNAL_IMMUTABLE_KEY}:true"`); + } + + if (tags.length > 0) { + filters.push( + `alert.attributes.tags:(${tags.map((tag) => `"${escapeKuery(tag)}"`).join(' AND ')})` + ); + } + + if (filter.length) { + const searchQuery = SEARCHABLE_RULE_PARAMS.map( + (param) => `${param}: "${escapeKuery(filter)}"` + ).join(' OR '); + + filters.push(`(${searchQuery})`); + } + + return filters.join(' AND '); }; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/actions.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/actions.ts index 10c099e4bfcc8..488fd3625bf59 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/actions.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/actions.ts @@ -81,25 +81,6 @@ export const executeRulesBulkAction = async ({ } }; -export const initRulesBulkAction = (params: Omit) => { - const byQuery = (query: string) => - executeRulesBulkAction({ - ...params, - search: { query }, - }); - - const byIds = (ids: string[]) => - executeRulesBulkAction({ - ...params, - search: { ids }, - }); - - return { - byQuery, - byIds, - }; -}; - function defaultErrorHandler(toasts: UseAppToasts, action: BulkAction, error: HTTPError) { // if response doesn't have number of failed rules, it means the whole bulk action failed // and general error toast will be shown. Otherwise - error toast for partial failure diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx index 491b693a442ba..6bd7cfc67f308 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx @@ -30,7 +30,7 @@ import { canEditRuleWithActions } from '../../../../../../common/utils/privilege import { useRulesTableContext } from '../rules_table/rules_table_context'; import * as detectionI18n from '../../../translations'; import * as i18n from '../../translations'; -import { executeRulesBulkAction, initRulesBulkAction } from '../actions'; +import { executeRulesBulkAction } from '../actions'; import { useHasActionsPrivileges } from '../use_has_actions_privileges'; import { useHasMlPermissions } from '../use_has_ml_permissions'; import { getCustomRulesCountFromCache } from './use_custom_rules_count'; @@ -239,26 +239,23 @@ export const useBulkActions = ({ ); }, 5 * 1000); - const rulesBulkAction = initRulesBulkAction({ + await executeRulesBulkAction({ visibleRuleIds: selectedRuleIds, action: BulkAction.edit, setLoadingRules, toasts, payload: { edit: [editPayload] }, onFinish: () => hideWarningToast(), + search: isAllSelected + ? { + query: convertRulesFilterToKQL({ + ...filterOptions, + showCustomRules: true, // only edit custom rules, as elastic rule are immutable + }), + } + : { ids: customSelectedRuleIds }, }); - // only edit custom rules, as elastic rule are immutable - if (isAllSelected) { - const customRulesOnlyFilterQuery = convertRulesFilterToKQL({ - ...filterOptions, - showCustomRules: true, - }); - await rulesBulkAction.byQuery(customRulesOnlyFilterQuery); - } else { - await rulesBulkAction.byIds(customSelectedRuleIds); - } - isBulkEditFinished = true; invalidateRules(); if (getIsMounted()) { diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/rules_table_context.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/rules_table_context.tsx index 2bf20acfb9334..130dd61c371ae 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/rules_table_context.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/rules_table_context.tsx @@ -16,7 +16,7 @@ import { SortingOptions, } from '../../../../../containers/detection_engine/rules/types'; import { useFindRules } from './use_find_rules'; -import { getRulesComparator, getRulesPredicate } from './utils'; +import { getRulesComparator } from './utils'; export interface RulesTableState { /** @@ -114,7 +114,7 @@ export interface LoadingRules { export interface RulesTableActions { reFetchRules: ReturnType['refetch']; - setFilterOptions: React.Dispatch>; + setFilterOptions: (newFilter: Partial) => void; setIsAllSelected: React.Dispatch>; setIsInMemorySorting: (value: boolean) => void; setIsRefreshOn: React.Dispatch>; @@ -186,6 +186,13 @@ export const RulesTableContextProvider = ({ const pagination = useMemo(() => ({ page, perPage }), [page, perPage]); + const handleFilterOptionsChange = useCallback((newFilter: Partial) => { + setFilterOptions((currentFilter) => ({ ...currentFilter, ...newFilter })); + setPage(1); + setSelectedRuleIds([]); + setIsAllSelected(false); + }, []); + // Fetch rules const { data: { rules, total } = { rules: [], total: 0 }, @@ -210,15 +217,10 @@ export const RulesTableContextProvider = ({ } }, [isFetched, isRefetching, refetchPrePackagedRulesStatus]); - // Filter rules - const filteredRules = isInMemorySorting ? rules.filter(getRulesPredicate(filterOptions)) : rules; - // Paginate and sort rules const rulesToDisplay = isInMemorySorting - ? filteredRules - .sort(getRulesComparator(sortingOptions)) - .slice((page - 1) * perPage, page * perPage) - : filteredRules; + ? rules.sort(getRulesComparator(sortingOptions)).slice((page - 1) * perPage, page * perPage) + : rules; const providerValue = useMemo( () => ({ @@ -227,7 +229,7 @@ export const RulesTableContextProvider = ({ pagination: { page, perPage, - total: isInMemorySorting ? filteredRules.length : total, + total: isInMemorySorting ? rules.length : total, }, filterOptions, isActionInProgress, @@ -246,7 +248,7 @@ export const RulesTableContextProvider = ({ }, actions: { reFetchRules: refetch, - setFilterOptions, + setFilterOptions: handleFilterOptionsChange, setIsAllSelected, setIsInMemorySorting: toggleInMemorySorting, setIsRefreshOn, @@ -260,7 +262,7 @@ export const RulesTableContextProvider = ({ [ dataUpdatedAt, filterOptions, - filteredRules.length, + handleFilterOptionsChange, isActionInProgress, isAllSelected, isFetched, @@ -274,6 +276,7 @@ export const RulesTableContextProvider = ({ page, perPage, refetch, + rules.length, rulesToDisplay, selectedRuleIds, sortingOptions, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/use_find_rules.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/use_find_rules.ts index 47a2617dd2e25..6544df7e7ed2a 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/use_find_rules.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/use_find_rules.ts @@ -31,8 +31,12 @@ export const useFindRules = (args: UseFindRulesArgs) => { // Use this query result when isInMemorySorting = true const allRules = useFindRulesQuery( ['all'], - { pagination: { page: 1, perPage: MAX_RULES_PER_PAGE } }, - { refetchInterval, enabled: isInMemorySorting } + { pagination: { page: 1, perPage: MAX_RULES_PER_PAGE }, filterOptions }, + { + refetchInterval, + enabled: isInMemorySorting, + keepPreviousData: true, // Use this option so that the state doesn't jump between "success" and "loading" on page change + } ); // Use this query result when isInMemorySorting = false diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/utils.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/utils.ts index 37deade0d1316..12d114cb3c990 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/utils.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table/utils.ts @@ -6,11 +6,7 @@ */ import { get } from 'lodash'; -import { - FilterOptions, - Rule, - SortingOptions, -} from '../../../../../containers/detection_engine/rules/types'; +import { Rule, SortingOptions } from '../../../../../containers/detection_engine/rules/types'; /** * Returns a comparator function to be used with .sort() @@ -79,29 +75,3 @@ const compareNumbers = (a: number, b: number, direction: number) => { } return 0; }; - -/** - * Returns a predicate function to be used with .filter() - * - * @param filterOptions Current table filter - */ -export function getRulesPredicate(filterOptions: FilterOptions) { - return (rule: Rule) => { - if ( - filterOptions.filter && - !rule.name.toLowerCase().includes(filterOptions.filter.toLowerCase()) - ) { - return false; - } - if (filterOptions.showCustomRules && rule.immutable) { - return false; - } - if (filterOptions.showElasticRules && !rule.immutable) { - return false; - } - if (filterOptions.tags.length && !filterOptions.tags.every((tag) => rule.tags.includes(tag))) { - return false; - } - return true; - }; -} diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.test.tsx index e627ce3815e59..816ffdfa9dad6 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.test.tsx @@ -7,65 +7,38 @@ import React from 'react'; import { mount } from 'enzyme'; -import { act } from '@testing-library/react'; import { RulesTableFilters } from './rules_table_filters'; -import { useAppToastsMock } from '../../../../../../common/hooks/use_app_toasts.mock'; -import { useAppToasts } from '../../../../../../common/hooks/use_app_toasts'; -jest.mock('../../../../../../common/hooks/use_app_toasts'); +import { TestProviders } from '../../../../../../common/mock'; -describe('RulesTableFilters', () => { - let appToastsMock: jest.Mocked>; - - beforeEach(() => { - jest.resetAllMocks(); - appToastsMock = useAppToastsMock.create(); - (useAppToasts as jest.Mock).mockReturnValue(appToastsMock); - }); +jest.mock('../rules_table/rules_table_context'); +describe('RulesTableFilters', () => { it('renders no numbers next to rule type button filter if none exist', async () => { - await act(async () => { - const wrapper = mount( - ({})} - /> - ); - - expect(wrapper.find('[data-test-subj="showElasticRulesFilterButton"]').at(0).text()).toEqual( - 'Elastic rules' - ); - expect(wrapper.find('[data-test-subj="showCustomRulesFilterButton"]').at(0).text()).toEqual( - 'Custom rules' - ); - }); + const wrapper = mount( + , + { wrappingComponent: TestProviders } + ); + + expect(wrapper.find('[data-test-subj="showElasticRulesFilterButton"]').at(0).text()).toEqual( + 'Elastic rules' + ); + expect(wrapper.find('[data-test-subj="showCustomRulesFilterButton"]').at(0).text()).toEqual( + 'Custom rules' + ); }); it('renders number of custom and prepackaged rules', async () => { - await act(async () => { - const wrapper = mount( - ({})} - /> - ); - - expect(wrapper.find('[data-test-subj="showElasticRulesFilterButton"]').at(0).text()).toEqual( - 'Elastic rules (9)' - ); - expect(wrapper.find('[data-test-subj="showCustomRulesFilterButton"]').at(0).text()).toEqual( - 'Custom rules (10)' - ); - }); + const wrapper = mount( + , + { wrappingComponent: TestProviders } + ); + + expect(wrapper.find('[data-test-subj="showElasticRulesFilterButton"]').at(0).text()).toEqual( + 'Elastic rules (9)' + ); + expect(wrapper.find('[data-test-subj="showCustomRulesFilterButton"]').at(0).text()).toEqual( + 'Custom rules (10)' + ); }); }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx index 5987cd75d303e..b4c81ae5a177d 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/rules_table_filters.tsx @@ -5,8 +5,6 @@ * 2.0. */ -import React, { useCallback, useEffect, useState } from 'react'; - import { EuiFieldSearch, EuiFilterButton, @@ -15,76 +13,63 @@ import { EuiFlexItem, } from '@elastic/eui'; import { isEqual } from 'lodash/fp'; - +import React, { useCallback } from 'react'; +import styled from 'styled-components'; import * as i18n from '../../translations'; - -import { FilterOptions } from '../../../../../containers/detection_engine/rules'; +import { useRulesTableContext } from '../rules_table/rules_table_context'; import { TagsFilterPopover } from './tags_filter_popover'; +const FilterWrapper = styled(EuiFlexGroup)` + margin-bottom: ${({ theme }) => theme.eui.euiSizeXS}; +`; + interface RulesTableFiltersProps { - onFilterChanged: (filterOptions: Partial) => void; rulesCustomInstalled: number | null; rulesInstalled: number | null; - currentFilterTags: string[]; - tags: string[]; - isLoadingTags: boolean; - reFetchTags: () => void; + allTags: string[]; } /** * Collection of filters for filtering data within the RulesTable. Contains search bar, Elastic/Custom * Rules filter button toggle, and tag selection - * - * @param onFilterChanged change listener to be notified on filter changes */ const RulesTableFiltersComponent = ({ - onFilterChanged, rulesCustomInstalled, rulesInstalled, - currentFilterTags, - tags, - isLoadingTags, - reFetchTags, + allTags, }: RulesTableFiltersProps) => { - const [filter, setFilter] = useState(''); - const [selectedTags, setSelectedTags] = useState([]); - const [showCustomRules, setShowCustomRules] = useState(false); - const [showElasticRules, setShowElasticRules] = useState(false); + const { + state: { filterOptions }, + actions: { setFilterOptions }, + } = useRulesTableContext(); - useEffect(() => { - reFetchTags(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [rulesCustomInstalled, rulesInstalled]); + const { showCustomRules, showElasticRules, tags: selectedTags } = filterOptions; - // Propagate filter changes to parent - useEffect(() => { - onFilterChanged({ filter, showCustomRules, showElasticRules, tags: selectedTags }); - }, [filter, selectedTags, showCustomRules, showElasticRules, onFilterChanged]); - - const handleOnSearch = useCallback((filterString) => setFilter(filterString.trim()), [setFilter]); + const handleOnSearch = useCallback( + (filterString) => setFilterOptions({ filter: filterString.trim() }), + [setFilterOptions] + ); const handleElasticRulesClick = useCallback(() => { - setShowElasticRules(!showElasticRules); - setShowCustomRules(false); - }, [setShowElasticRules, showElasticRules, setShowCustomRules]); + setFilterOptions({ showElasticRules: !showElasticRules, showCustomRules: false }); + }, [setFilterOptions, showElasticRules]); const handleCustomRulesClick = useCallback(() => { - setShowCustomRules(!showCustomRules); - setShowElasticRules(false); - }, [setShowElasticRules, showCustomRules, setShowCustomRules]); + setFilterOptions({ showCustomRules: !showCustomRules, showElasticRules: false }); + }, [setFilterOptions, showCustomRules]); const handleSelectedTags = useCallback( - (newTags) => { + (newTags: string[]) => { if (!isEqual(newTags, selectedTags)) { - setSelectedTags(newTags); + setFilterOptions({ tags: newTags }); } }, - [selectedTags] + [selectedTags, setFilterOptions] ); return ( - - + + - @@ -123,14 +105,12 @@ const RulesTableFiltersComponent = ({ onClick={handleCustomRulesClick} data-test-subj="showCustomRulesFilterButton" > - <> - {i18n.CUSTOM_RULES} - {rulesCustomInstalled != null ? ` (${rulesCustomInstalled})` : ''} - + {i18n.CUSTOM_RULES} + {rulesCustomInstalled != null ? ` (${rulesCustomInstalled})` : ''} - + ); }; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.test.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.test.tsx index bb41c2d87cd5a..c8b5e78a94563 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.test.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.test.tsx @@ -13,13 +13,7 @@ import { TagsFilterPopover } from './tags_filter_popover'; describe('TagsFilterPopover', () => { it('renders correctly', () => { const wrapper = shallow( - + ); expect(wrapper.find('EuiPopover')).toHaveLength(1); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx index c5262caf6c776..ca2c2b4d00d30 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_table_filters/tags_filter_popover.tsx @@ -5,15 +5,7 @@ * 2.0. */ -import React, { - ChangeEvent, - Dispatch, - SetStateAction, - useCallback, - useEffect, - useMemo, - useState, -} from 'react'; +import React, { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react'; import { EuiFilterButton, EuiFilterSelectItem, @@ -33,10 +25,7 @@ import { caseInsensitiveSort } from '../helpers'; interface TagsFilterPopoverProps { selectedTags: string[]; tags: string[]; - onSelectedTagsChanged: Dispatch>; - currentFilterTags: string[]; - // eslint-disable-next-line react/no-unused-prop-types - isLoading: boolean; // TO DO reimplement? + onSelectedTagsChanged: (newTags: string[]) => void; } const PopoverContentWrapper = styled.div` @@ -64,11 +53,10 @@ const TagsFilterPopoverComponent = ({ tags, selectedTags, onSelectedTagsChanged, - currentFilterTags, }: TagsFilterPopoverProps) => { const sortedTags = useMemo( - () => caseInsensitiveSort(Array.from(new Set([...tags, ...currentFilterTags]))), - [tags, currentFilterTags] + () => caseInsensitiveSort(Array.from(new Set([...tags, ...selectedTags]))), + [selectedTags, tags] ); const [isTagPopoverOpen, setIsTagPopoverOpen] = useState(false); const [searchInput, setSearchInput] = useState(''); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_tables.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_tables.tsx index c38c8e48928f1..3962fa217ccfb 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_tables.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/rules_tables.tsx @@ -14,19 +14,16 @@ import { EuiLoadingContent, EuiProgress, } from '@elastic/eui'; -import React, { useCallback, useMemo, useRef } from 'react'; +import React, { useCallback, useEffect, useMemo, useRef } from 'react'; import { partition } from 'lodash/fp'; import { AllRulesTabs } from './rules_table_toolbar'; -import { HeaderSection } from '../../../../../common/components/header_section'; import { Loader } from '../../../../../common/components/loader'; import { useBoolState } from '../../../../../common/hooks/use_bool_state'; import { useValueChanged } from '../../../../../common/hooks/use_value_changed'; -import { useKibana } from '../../../../../common/lib/kibana'; import { PrePackagedRulesPrompt } from '../../../../components/rules/pre_packaged_rules/load_empty_prompt'; import { CreatePreBuiltRules, - FilterOptions, Rule, RulesSortingFields, } from '../../../../containers/detection_engine/rules'; @@ -85,7 +82,6 @@ export const RulesTables = React.memo( rulesNotUpdated, selectedTab, }) => { - const { timelines } = useKibana().services; const tableRef = useRef(null); const rulesTableContext = useRulesTableContext(); @@ -96,11 +92,9 @@ export const RulesTables = React.memo( isActionInProgress, isAllSelected, isFetched, - isFetching, isLoading, isRefetching, isRefreshOn, - lastUpdated, loadingRuleIds, loadingRulesAction, pagination, @@ -109,7 +103,6 @@ export const RulesTables = React.memo( }, actions: { reFetchRules, - setFilterOptions, setIsAllSelected, setIsRefreshOn, setPage, @@ -125,7 +118,12 @@ export const RulesTables = React.memo( rulesNotUpdated ); - const [isLoadingTags, tags, reFetchTags] = useTags(); + const [, allTags, reFetchTags] = useTags(); + + useEffect(() => { + reFetchTags(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [rulesCustomInstalled, rulesInstalled]); const [isDeleteConfirmationVisible, showDeleteConfirmation, hideDeleteConfirmation] = useBoolState(); @@ -183,16 +181,6 @@ export const RulesTables = React.memo( [pagination] ); - const onFilterChangedCallback = useCallback( - (newFilter: Partial) => { - setFilterOptions((currentFilter) => ({ ...currentFilter, ...newFilter })); - setPage(1); - setSelectedRuleIds([]); - setIsAllSelected(false); - }, - [setFilterOptions, setIsAllSelected, setPage, setSelectedRuleIds] - ); - const tableOnChangeCallback = useCallback( ({ page, sort }: EuiBasicTableOnChange) => { setSortingOptions({ @@ -286,9 +274,11 @@ export const RulesTables = React.memo( } : { 'data-test-subj': 'monitoring-table', columns: monitoringColumns }; + const shouldShowLinearProgress = isFetched && isRefetching; + const shouldShowLoadingOverlay = (!isFetched && isRefetching) || isActionInProgress; return ( <> - {isFetched && isRefetching && ( + {shouldShowLinearProgress && ( ( color="accent" /> )} - {((!isFetched && isRefetching) || isActionInProgress) && ( + {shouldShowLoadingOverlay && ( )} - - {shouldShowRulesTable && ( - - )} - + {shouldShowRulesTable && ( + + )} {shouldShowPrepackagedRulesPrompt && ( ( editAction={bulkEditActionType} onClose={handleBulkEditFormCancel} onConfirm={handleBulkEditFormConfirm} - tags={tags} + tags={allTags} /> )} {shouldShowRulesTable && ( diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/utility_bar.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/utility_bar.tsx index 6d9c2f92b214e..5513f70c42297 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/utility_bar.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/utility_bar.tsx @@ -22,6 +22,8 @@ import { UtilityBarText, } from '../../../../../common/components/utility_bar'; import * as i18n from '../translations'; +import { useKibana } from '../../../../../common/lib/kibana'; +import { useRulesTableContextOptional } from './rules_table/rules_table_context'; interface AllRulesUtilityBarProps { canBulkEdit: boolean; @@ -55,6 +57,9 @@ export const AllRulesUtilityBar = React.memo( isBulkActionInProgress, hasDisabledActions, }) => { + const { timelines } = useKibana().services; + const rulesTableContext = useRulesTableContextOptional(); + const handleGetBulkItemsPopoverContent = useCallback( (closePopover: () => void): JSX.Element | null => { if (onGetBulkItemsPopoverContent != null) { @@ -100,7 +105,7 @@ export const AllRulesUtilityBar = React.memo( ); return ( - + {hasBulkActions ? ( @@ -180,6 +185,14 @@ export const AllRulesUtilityBar = React.memo( )} + {rulesTableContext && ( + + {timelines.getLastUpdated({ + showUpdating: rulesTableContext.state.isFetching, + updatedAt: rulesTableContext.state.lastUpdated, + })} + + )} ); } diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts index 55a564f472c59..f93ca2f48d2db 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts @@ -391,13 +391,6 @@ export const EXPORT_FILENAME = i18n.translate( } ); -export const ALL_RULES = i18n.translate( - 'xpack.securitySolution.detectionEngine.rules.allRules.tableTitle', - { - defaultMessage: 'All rules', - } -); - export const SEARCH_RULES = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.allRules.searchAriaLabel', { @@ -408,7 +401,7 @@ export const SEARCH_RULES = i18n.translate( export const SEARCH_PLACEHOLDER = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.allRules.searchPlaceholder', { - defaultMessage: 'e.g. rule name', + defaultMessage: 'Search by rule name, index pattern, or MITRE ATT&CK tactic or technique', } ); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 7b6e87e2d49db..ddb2ca0490c48 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -20830,14 +20830,12 @@ "xpack.securitySolution.detectionEngine.rules.allRules.inactiveRuleDescription": "inactive", "xpack.securitySolution.detectionEngine.rules.allRules.refreshTitle": "Actualiser", "xpack.securitySolution.detectionEngine.rules.allRules.searchAriaLabel": "Rechercher les règles", - "xpack.securitySolution.detectionEngine.rules.allRules.searchPlaceholder": "par ex. nom de règle", "xpack.securitySolution.detectionEngine.rules.allRules.selectAllRulesTitle": "Sélection totale de {totalRules} {totalRules, plural, =1 {règle} other {règles}} effectuée", "xpack.securitySolution.detectionEngine.rules.allRules.selectedRulesTitle": "Sélection de {selectedRules} {selectedRules, plural, =1 {règle} other {règles}} effectuée", "xpack.securitySolution.detectionEngine.rules.allRules.showingExceptionLists": "Affichage de {totalLists} {totalLists, plural, =1 {liste} other {listes}}", "xpack.securitySolution.detectionEngine.rules.allRules.showingRulesTitle": "Affichage de {totalRules} {totalRules, plural, =1 {règle} other {règles}}", "xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.duplicate.successToastDescription": "Duplication réussie de {totalRules, plural, =1 {{totalRules} règle} other {{totalRules} règles}}", "xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.export.successToastDescription": "Exportation réussie de {exportedRules} sur {totalRules} {totalRules, plural, =1 {règle} other {règles}}. Les règles prédéfinies ont été exclues du fichier résultant.", - "xpack.securitySolution.detectionEngine.rules.allRules.tableTitle": "Toutes les règles", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.exceptions": "Listes d'exceptions", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.monitoring": "Monitoring des règles", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.rules": "Règles", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index e465e82dfa5d5..cc840ab4a3534 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -23836,14 +23836,12 @@ "xpack.securitySolution.detectionEngine.rules.allRules.inactiveRuleDescription": "非アクティブ", "xpack.securitySolution.detectionEngine.rules.allRules.refreshTitle": "更新", "xpack.securitySolution.detectionEngine.rules.allRules.searchAriaLabel": "ルールの検索", - "xpack.securitySolution.detectionEngine.rules.allRules.searchPlaceholder": "例:ルール名", "xpack.securitySolution.detectionEngine.rules.allRules.selectAllRulesTitle": "すべての{totalRules} {totalRules, plural, other {個のルール}}を選択", "xpack.securitySolution.detectionEngine.rules.allRules.selectedRulesTitle": "{selectedRules} {selectedRules, plural, other {ルール}}を選択しました", "xpack.securitySolution.detectionEngine.rules.allRules.showingExceptionLists": "{totalLists} {totalLists, plural, other {件のリスト}}を表示しています。", "xpack.securitySolution.detectionEngine.rules.allRules.showingRulesTitle": "{totalRules} {totalRules, plural, other {ルール}}を表示中", "xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.duplicate.successToastDescription": "{totalRules, plural, other {{totalRules}ルール}}を正常に複製しました", "xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.export.successToastDescription": "{exportedRules}/{totalRules} {totalRules, plural, other {件のルール}}を正常にエクスポートしました事前構築済みルールは結果のファイルから除外されました。", - "xpack.securitySolution.detectionEngine.rules.allRules.tableTitle": "すべてのルール", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.exceptions": "例外リスト", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.monitoring": "ルール監視", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.rules": "ルール", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 737ad8b6e116c..8697109f3b927 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -23863,14 +23863,12 @@ "xpack.securitySolution.detectionEngine.rules.allRules.inactiveRuleDescription": "非活动", "xpack.securitySolution.detectionEngine.rules.allRules.refreshTitle": "刷新", "xpack.securitySolution.detectionEngine.rules.allRules.searchAriaLabel": "搜索规则", - "xpack.securitySolution.detectionEngine.rules.allRules.searchPlaceholder": "例如,规则名", "xpack.securitySolution.detectionEngine.rules.allRules.selectAllRulesTitle": "选择所有 {totalRules} 个{totalRules, plural, other {规则}}", "xpack.securitySolution.detectionEngine.rules.allRules.selectedRulesTitle": "已选择 {selectedRules} 个{selectedRules, plural, other {规则}}", "xpack.securitySolution.detectionEngine.rules.allRules.showingExceptionLists": "正在显示 {totalLists} 个{totalLists, plural, other {列表}}", "xpack.securitySolution.detectionEngine.rules.allRules.showingRulesTitle": "正在显示 {totalRules} 个{totalRules, plural, other {规则}}", "xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.duplicate.successToastDescription": "已成功复制 {totalRules, plural, other {{totalRules} 个规则}}", "xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.export.successToastDescription": "已成功导出 {exportedRules}/{totalRules} 个{totalRules, plural, other {规则}}。预置规则已从结果文件中排除。", - "xpack.securitySolution.detectionEngine.rules.allRules.tableTitle": "所有规则", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.exceptions": "例外列表", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.monitoring": "规则监测", "xpack.securitySolution.detectionEngine.rules.allRules.tabs.rules": "规则", From 617bb305c90bd97683febab280387d0c478d1bb7 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Tue, 29 Mar 2022 10:19:40 +0200 Subject: [PATCH 04/31] [Discover] Cleanup usage of deprecated APIs (#128602) --- src/plugins/discover/public/__mocks__/services.ts | 6 ++---- .../context/services/context_state.test.ts | 3 ++- .../application/main/components/chart/histogram.tsx | 4 ++-- .../main/components/layout/discover_layout.test.tsx | 4 ---- .../__stories__/discover_field_details.stories.tsx | 5 +++-- .../components/sidebar/discover_sidebar.test.tsx | 8 +++----- .../sidebar/discover_sidebar_responsive.test.tsx | 7 +++---- .../public/embeddable/saved_search_embeddable.tsx | 12 ++++-------- .../components/doc_viewer_source/get_height.test.tsx | 3 ++- 9 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/plugins/discover/public/__mocks__/services.ts b/src/plugins/discover/public/__mocks__/services.ts index bc66ae363711e..5f9511d2a63fe 100644 --- a/src/plugins/discover/public/__mocks__/services.ts +++ b/src/plugins/discover/public/__mocks__/services.ts @@ -21,6 +21,7 @@ import { UI_SETTINGS } from '../../../data/public'; import { TopNavMenu } from '../../../navigation/public'; import { FORMATS_UI_SETTINGS } from 'src/plugins/field_formats/common'; import { LocalStorageMock } from './local_storage_mock'; +import { fieldFormatsMock } from '../../../field_formats/common/mocks'; const dataPlugin = dataPluginMock.createStartContract(); export const discoverServiceMock = { @@ -45,10 +46,7 @@ export const discoverServiceMock = { save: true, }, }, - fieldFormats: { - getDefaultInstance: jest.fn(() => ({ convert: (value: unknown) => value })), - getFormatterForField: jest.fn(() => ({ convert: (value: unknown) => value })), - }, + fieldFormats: fieldFormatsMock, filterManager: dataPlugin.query.filterManager, uiSettings: { get: jest.fn((key: string) => { diff --git a/src/plugins/discover/public/application/context/services/context_state.test.ts b/src/plugins/discover/public/application/context/services/context_state.test.ts index 8f564d56c1042..3eb0e8a1e85d4 100644 --- a/src/plugins/discover/public/application/context/services/context_state.test.ts +++ b/src/plugins/discover/public/application/context/services/context_state.test.ts @@ -6,10 +6,11 @@ * Side Public License, v 1. */ +import { Filter } from '@kbn/es-query'; import { IUiSettingsClient } from 'kibana/public'; import { getState } from './context_state'; import { createBrowserHistory, History } from 'history'; -import { FilterManager, Filter } from '../../../../../data/public'; +import { FilterManager } from '../../../../../data/public'; import { coreMock } from '../../../../../../core/public/mocks'; import { SEARCH_FIELDS_FROM_SOURCE } from '../../../../common'; diff --git a/src/plugins/discover/public/application/main/components/chart/histogram.tsx b/src/plugins/discover/public/application/main/components/chart/histogram.tsx index 369513d3b7a31..22eff35be2325 100644 --- a/src/plugins/discover/public/application/main/components/chart/histogram.tsx +++ b/src/plugins/discover/public/application/main/components/chart/histogram.tsx @@ -65,7 +65,7 @@ export function DiscoverHistogram({ savedSearchData$, timefilterUpdateHandler, }: DiscoverHistogramProps) { - const { data, theme, uiSettings } = useDiscoverServices(); + const { data, theme, uiSettings, fieldFormats } = useDiscoverServices(); const chartTheme = theme.useChartsTheme(); const chartBaseTheme = theme.useChartsBaseTheme(); @@ -207,7 +207,7 @@ export function DiscoverHistogram({ type: TooltipType.VerticalCursor, }; - const xAxisFormatter = data.fieldFormats.deserialize(chartData.yAxisFormat); + const xAxisFormatter = fieldFormats.deserialize(chartData.yAxisFormat); const useLegacyTimeAxis = uiSettings.get(LEGACY_TIME_AXIS, false); diff --git a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx index c9a9ea6441a0b..6ff808a65eb5e 100644 --- a/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx +++ b/src/plugins/discover/public/application/main/components/layout/discover_layout.test.tsx @@ -43,10 +43,6 @@ function mountComponent(indexPattern: DataView, prevSidebarClosed?: boolean) { const searchSourceMock = createSearchSourceMock({}); const services = { ...discoverServiceMock, - fieldFormats: { - getDefaultInstance: jest.fn(() => ({ convert: (value: unknown) => value })), - getFormatterForField: jest.fn(() => ({ convert: (value: unknown) => value })), - }, storage: new LocalStorageMock({ [SIDEBAR_CLOSED_KEY]: prevSidebarClosed, }) as unknown as Storage, diff --git a/src/plugins/discover/public/application/main/components/sidebar/__stories__/discover_field_details.stories.tsx b/src/plugins/discover/public/application/main/components/sidebar/__stories__/discover_field_details.stories.tsx index 2951840b834b0..3547359209700 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/__stories__/discover_field_details.stories.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/__stories__/discover_field_details.stories.tsx @@ -10,7 +10,8 @@ import { storiesOf } from '@storybook/react'; import React from 'react'; import { KBN_FIELD_TYPES } from '@kbn/field-types'; import { DiscoverFieldDetails } from '../discover_field_details'; -import { DataView, IndexPatternField } from '../../../../../../../data_views/public'; +import { DataViewField } from '../../../../../../../data_views/public'; +import { DataView } from '../../../../../../../data_views/public'; import { fieldSpecMap } from './fields'; import { numericField as field } from './fields'; import { Bucket } from '../types'; @@ -36,7 +37,7 @@ const fieldFormat = { defaultMap, }; -const scriptedField = new IndexPatternField({ +const scriptedField = new DataViewField({ name: 'machine.os', type: 'string', esTypes: ['long'], diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx index 266174a002271..3d3c4b9da4516 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar.test.tsx @@ -31,11 +31,9 @@ import { AvailableFields$ } from '../../utils/use_saved_search'; function getCompProps(): DiscoverSidebarProps { const indexPattern = stubLogstashIndexPattern; - - // @ts-expect-error _.each() is passing additional args to flattenHit - const hits = each(cloneDeep(realHits), indexPattern.flattenHit) as Array< - Record - > as ElasticSearchHit[]; + const hits = each(cloneDeep(realHits), (hit) => + flattenHit(hit, indexPattern) + ) as unknown as ElasticSearchHit[]; const indexPatternList = [ { id: '0', attributes: { title: 'b' } } as SavedObject, diff --git a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx index 05e0e25d606f6..ef8fcd145c908 100644 --- a/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx +++ b/src/plugins/discover/public/application/main/components/sidebar/discover_sidebar_responsive.test.tsx @@ -73,10 +73,9 @@ jest.mock('../../utils/calc_field_counts', () => ({ function getCompProps(): DiscoverSidebarResponsiveProps { const indexPattern = stubLogstashIndexPattern; - // @ts-expect-error _.each() is passing additional args to flattenHit - const hits = each(cloneDeep(realHits), (hit) => flattenHit(hit, indexPattern)) as Array< - Record - > as ElasticSearchHit[]; + const hits = each(cloneDeep(realHits), (hit) => + flattenHit(hit, indexPattern) + ) as unknown as ElasticSearchHit[]; const indexPatternList = [ { id: '0', attributes: { title: 'b' } } as SavedObject, diff --git a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx index f67adf0976e59..e5a8fb2898e4b 100644 --- a/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx +++ b/src/plugins/discover/public/embeddable/saved_search_embeddable.tsx @@ -7,6 +7,7 @@ */ import { Subscription } from 'rxjs'; +import { onlyDisabledFiltersChanged, Filter } from '@kbn/es-query'; import React from 'react'; import ReactDOM from 'react-dom'; import { i18n } from '@kbn/i18n'; @@ -18,14 +19,9 @@ import { ISearchEmbeddable, SearchInput, SearchOutput } from './types'; import { SavedSearch } from '../services/saved_searches'; import { Adapters, RequestAdapter } from '../../../inspector/common'; import { SEARCH_EMBEDDABLE_TYPE } from './constants'; -import { - APPLY_FILTER_TRIGGER, - esFilters, - FilterManager, - generateFilters, -} from '../../../data/public'; +import { APPLY_FILTER_TRIGGER, FilterManager, generateFilters } from '../../../data/public'; import { DiscoverServices } from '../build_services'; -import { Filter, ISearchSource, Query, TimeRange, FilterStateStore } from '../../../data/public'; +import { ISearchSource, Query, TimeRange, FilterStateStore } from '../../../data/public'; import { DataView, DataViewField } from '../../../data_views/public'; import { SavedSearchEmbeddableComponent } from './saved_search_embeddable_component'; import { UiActionsStart } from '../../../ui_actions/public'; @@ -332,7 +328,7 @@ export class SavedSearchEmbeddable { forceFetch = false }: { forceFetch: boolean } = { forceFetch: false } ) { const isFetchRequired = - !esFilters.onlyDisabledFiltersChanged(this.input.filters, this.prevFilters) || + !onlyDisabledFiltersChanged(this.input.filters, this.prevFilters) || !isEqual(this.prevQuery, this.input.query) || !isEqual(this.prevTimeRange, this.input.timeRange) || !isEqual(searchProps.sort, this.input.sort || this.savedSearch.sort) || diff --git a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx b/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx index 5b641cced5163..fc8f7498f6efc 100644 --- a/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx +++ b/src/plugins/discover/public/services/doc_views/components/doc_viewer_source/get_height.test.tsx @@ -10,7 +10,8 @@ import { monaco } from '@kbn/monaco'; import { getHeight } from './get_height'; describe('getHeight', () => { - window.innerHeight = 500; + Object.defineProperty(window, 'innerHeight', { writable: true, configurable: true, value: 500 }); + const getMonacoMock = (lineCount: number) => { return { getDomNode: jest.fn(() => { From aa4ce92457ff968903559d2d623302380c326286 Mon Sep 17 00:00:00 2001 From: Aleh Zasypkin Date: Tue, 29 Mar 2022 10:44:00 +0200 Subject: [PATCH 05/31] Update API keys docs to remove unnecessary API keys service section. (#128464) --- docs/user/security/api-keys/index.asciidoc | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/docs/user/security/api-keys/index.asciidoc b/docs/user/security/api-keys/index.asciidoc index 94301568b6438..bc277609d43e4 100644 --- a/docs/user/security/api-keys/index.asciidoc +++ b/docs/user/security/api-keys/index.asciidoc @@ -19,20 +19,6 @@ To manage API keys, open the main menu, then click *Stack Management > API Keys* [role="screenshot"] image:images/api-keys.png["API Keys UI"] -[float] -[[api-keys-service]] -=== {es} API key service - -The {es} API key service is automatically enabled when you configure -{ref}/configuring-tls.html#tls-http[TLS on the HTTP interface]. -This ensures that clients are unable to send API keys in clear-text. - -When HTTPS connections are not enabled between {kib} and {es}, -you cannot create or manage API keys, and you get an error message. -For more information, see the -{ref}/security-api-create-api-key.html[{es} API key documentation], -or contact your system administrator. - [float] [[api-keys-security-privileges]] === Security privileges From bef90a58663b6c4b668a7fe0ce45a002fb68c474 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Tue, 29 Mar 2022 10:44:11 +0200 Subject: [PATCH 06/31] Jest axe a11y testing (#127185) * [A11y] Added axe testing to testBed to be used in jest tests (CITs) * [A11y] Refactored axe helpers to be outside of testBed for better separation of concerns. Also added tests for indices tab in Index Management. * [A11y] Switched `axe_helpers` to use a Kibana wide axe config and rules that are now in kbn-test package * [A11y] Switched `axe_helpers` to use a Kibana wide axe config and rules that are now in kbn-test package * [A11y] Completed a11y tests in Index Management Indices tab. Also refactored http requests helper file. * Removed import comment * Reverted yarn.lock change * Correct yarn.lock changes * [IM] Updated the branch after merging main * [IM] Reverted unrelated ResponseError interface changes * [IM] Fixed eslint issue with kbn/test import --- package.json | 2 + packages/kbn-test-jest-helpers/BUILD.bazel | 5 + .../kbn-test-jest-helpers/src/axe_helpers.ts | 35 +++++ packages/kbn-test-jest-helpers/src/index.ts | 2 + .../src/testbed/types.ts | 2 +- packages/kbn-test/BUILD.bazel | 1 + .../kbn-test/src/a11y/config.ts | 0 packages/kbn-test/src/index.ts | 2 + test/accessibility/services/a11y/a11y.ts | 2 +- .../apm/ftr_e2e/cypress/support/commands.ts | 5 +- .../applications/shared/cypress/commands.ts | 6 +- .../__jest__/a11y/indices_tab.a11y.test.ts | 125 ++++++++++++++++++ .../client_integration/helpers/fixtures.ts | 47 +++++++ .../helpers/http_requests.ts | 17 ++- .../client_integration/helpers/index.ts | 2 + .../helpers/test_subjects.ts | 3 +- yarn.lock | 85 ++++++++++-- 17 files changed, 317 insertions(+), 24 deletions(-) create mode 100644 packages/kbn-test-jest-helpers/src/axe_helpers.ts rename test/accessibility/services/a11y/constants.ts => packages/kbn-test/src/a11y/config.ts (100%) create mode 100644 x-pack/plugins/index_management/__jest__/a11y/indices_tab.a11y.test.ts create mode 100644 x-pack/plugins/index_management/__jest__/client_integration/helpers/fixtures.ts diff --git a/package.json b/package.json index b8ec92ab796d6..4eba243e30b8a 100644 --- a/package.json +++ b/package.json @@ -571,6 +571,7 @@ "@types/inquirer": "^7.3.1", "@types/intl-relativeformat": "^2.1.0", "@types/jest": "^26.0.22", + "@types/jest-axe": "^3.5.3", "@types/jest-specific-snapshot": "^0.5.5", "@types/joi": "^17.2.3", "@types/jquery": "^3.3.31", @@ -821,6 +822,7 @@ "is-glob": "^4.0.1", "is-path-inside": "^3.0.2", "jest": "^26.6.3", + "jest-axe": "^5.0.0", "jest-canvas-mock": "^2.3.1", "jest-circus": "^26.6.3", "jest-cli": "^26.6.3", diff --git a/packages/kbn-test-jest-helpers/BUILD.bazel b/packages/kbn-test-jest-helpers/BUILD.bazel index d910fab5295d5..c97859e8baab1 100644 --- a/packages/kbn-test-jest-helpers/BUILD.bazel +++ b/packages/kbn-test-jest-helpers/BUILD.bazel @@ -34,6 +34,7 @@ NPM_MODULE_EXTRA_FILES = [ RUNTIME_DEPS = [ "//packages/kbn-dev-utils", "//packages/kbn-i18n-react", + "//packages/kbn-test", "//packages/kbn-std", "//packages/kbn-utils", "@npm//@elastic/elasticsearch", @@ -51,6 +52,7 @@ RUNTIME_DEPS = [ "@npm//he", "@npm//history", "@npm//jest", + "@npm//jest-axe", "@npm//jest-cli", "@npm//jest-snapshot", "@npm//jest-styled-components", @@ -76,9 +78,11 @@ TYPES_DEPS = [ "//packages/kbn-dev-utils:npm_module_types", "//packages/kbn-i18n-react:npm_module_types", "//packages/kbn-std:npm_module_types", + "//packages/kbn-test:npm_module_types", "//packages/kbn-utils:npm_module_types", "@npm//@elastic/elasticsearch", "@npm//axios", + "@npm//axe-core", "@npm//elastic-apm-node", "@npm//del", "@npm//exit-hook", @@ -96,6 +100,7 @@ TYPES_DEPS = [ "@npm//@types/he", "@npm//@types/history", "@npm//@types/jest", + "@npm//@types/jest-axe", "@npm//@types/joi", "@npm//@types/lodash", "@npm//@types/mustache", diff --git a/packages/kbn-test-jest-helpers/src/axe_helpers.ts b/packages/kbn-test-jest-helpers/src/axe_helpers.ts new file mode 100644 index 0000000000000..215209546f956 --- /dev/null +++ b/packages/kbn-test-jest-helpers/src/axe_helpers.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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { configureAxe } from 'jest-axe'; +import { Result } from 'axe-core'; +import { AXE_OPTIONS, AXE_CONFIG } from '@kbn/test'; +import { ReactWrapper } from './testbed/types'; + +const axeRunner = configureAxe({ globalOptions: { ...AXE_CONFIG } }); + +/** + * Function to test if a component doesn't have a11y violations from axe automated testing + * @param component + */ +export const expectToBeAccessible = async (component: ReactWrapper): Promise => { + const violations = await getA11yViolations(component); + expect(violations).toHaveLength(0); +}; + +/** + * Returns a11y violations as found by axe testing + * @param component + */ +export const getA11yViolations = async (component: ReactWrapper): Promise => { + const axeResults = await axeRunner(component.html(), { + ...AXE_OPTIONS, + resultTypes: ['violations'], + }); + return axeResults.violations; +}; diff --git a/packages/kbn-test-jest-helpers/src/index.ts b/packages/kbn-test-jest-helpers/src/index.ts index 3594df854cbe4..809d4380df10a 100644 --- a/packages/kbn-test-jest-helpers/src/index.ts +++ b/packages/kbn-test-jest-helpers/src/index.ts @@ -24,6 +24,8 @@ export * from './stub_web_worker'; export * from './testbed'; +export * from './axe_helpers'; + export const nextTick = () => new Promise((res) => process.nextTick(res)); export const delay = (time = 0) => new Promise((resolve) => setTimeout(resolve, time)); diff --git a/packages/kbn-test-jest-helpers/src/testbed/types.ts b/packages/kbn-test-jest-helpers/src/testbed/types.ts index 11f8c802a9751..15996646ec80a 100644 --- a/packages/kbn-test-jest-helpers/src/testbed/types.ts +++ b/packages/kbn-test-jest-helpers/src/testbed/types.ts @@ -30,7 +30,7 @@ export interface EuiTableMetaData { } export interface TestBed { - /** The comonent under test */ + /** The component under test */ component: ReactWrapper; /** * Pass it a `data-test-subj` and it will return true if it exists or false if it does not exist. diff --git a/packages/kbn-test/BUILD.bazel b/packages/kbn-test/BUILD.bazel index 4dc8d684941f3..99d8c64c88032 100644 --- a/packages/kbn-test/BUILD.bazel +++ b/packages/kbn-test/BUILD.bazel @@ -86,6 +86,7 @@ TYPES_DEPS = [ "@npm//@elastic/elasticsearch", "@npm//@jest/console", "@npm//@jest/reporters", + "@npm//axe-core", "@npm//axios", "@npm//elastic-apm-node", "@npm//del", diff --git a/test/accessibility/services/a11y/constants.ts b/packages/kbn-test/src/a11y/config.ts similarity index 100% rename from test/accessibility/services/a11y/constants.ts rename to packages/kbn-test/src/a11y/config.ts diff --git a/packages/kbn-test/src/index.ts b/packages/kbn-test/src/index.ts index c9f0e67c558f1..a0e45f9d7b752 100644 --- a/packages/kbn-test/src/index.ts +++ b/packages/kbn-test/src/index.ts @@ -69,3 +69,5 @@ export { runJest } from './jest/run'; export * from './kbn_archiver_cli'; export * from './kbn_client'; + +export { AXE_CONFIG, AXE_OPTIONS } from './a11y/config'; diff --git a/test/accessibility/services/a11y/a11y.ts b/test/accessibility/services/a11y/a11y.ts index f4d5ceba5a6e3..fd4362c1c82b4 100644 --- a/test/accessibility/services/a11y/a11y.ts +++ b/test/accessibility/services/a11y/a11y.ts @@ -8,9 +8,9 @@ import chalk from 'chalk'; import testSubjectToCss from '@kbn/test-subj-selector'; +import { AXE_CONFIG, AXE_OPTIONS } from '@kbn/test'; import { FtrService } from '../../ftr_provider_context'; -import { AXE_CONFIG, AXE_OPTIONS } from './constants'; import { AxeReport, printResult } from './axe_report'; // @ts-ignore JS that is run in browser as is import { analyzeWithAxe, analyzeWithAxeWithClient } from './analyze_with_axe'; diff --git a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts index 91edae9046f6d..89d8fa620c183 100644 --- a/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts +++ b/x-pack/plugins/apm/ftr_e2e/cypress/support/commands.ts @@ -7,10 +7,7 @@ import 'cypress-real-events/support'; import { Interception } from 'cypress/types/net-stubbing'; import 'cypress-axe'; -import { - AXE_CONFIG, - AXE_OPTIONS, -} from 'test/accessibility/services/a11y/constants'; +import { AXE_CONFIG, AXE_OPTIONS } from '@kbn/test'; Cypress.Commands.add('loginAsReadOnlyUser', () => { cy.loginAs({ username: 'apm_read_user', password: 'changeme' }); diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/cypress/commands.ts b/x-pack/plugins/enterprise_search/public/applications/shared/cypress/commands.ts index 475343948f348..083d55e6f7029 100644 --- a/x-pack/plugins/enterprise_search/public/applications/shared/cypress/commands.ts +++ b/x-pack/plugins/enterprise_search/public/applications/shared/cypress/commands.ts @@ -38,9 +38,11 @@ export const login = ({ * Cypress setup/helpers */ +// eslint complains this should be in `dependencies` and not `devDependencies`, but these tests should only run on dev // eslint-disable-next-line import/no-extraneous-dependencies -import 'cypress-axe'; // eslint complains this should be in `dependencies` and not `devDependencies`, but these tests should only run on dev -import { AXE_CONFIG, AXE_OPTIONS } from 'test/accessibility/services/a11y/constants'; +import 'cypress-axe'; +// eslint-disable-next-line import/no-extraneous-dependencies +import { AXE_CONFIG, AXE_OPTIONS } from '@kbn/test'; const axeConfig = { ...AXE_CONFIG, diff --git a/x-pack/plugins/index_management/__jest__/a11y/indices_tab.a11y.test.ts b/x-pack/plugins/index_management/__jest__/a11y/indices_tab.a11y.test.ts new file mode 100644 index 0000000000000..dada1c0fc91c5 --- /dev/null +++ b/x-pack/plugins/index_management/__jest__/a11y/indices_tab.a11y.test.ts @@ -0,0 +1,125 @@ +/* + * 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 { act } from 'react-dom/test-utils'; +// import { expectToBeAccessible } from '@kbn/test-jest-helpers'; +import { getA11yViolations } from '@kbn/test-jest-helpers'; +import { IndicesTestBed, setup } from '../client_integration/home/indices_tab.helpers'; +import { + indexMappings, + indexSettings, + indexStats, + setupEnvironment, +} from '../client_integration/helpers'; +import { + createDataStreamBackingIndex, + createNonDataStreamIndex, +} from '../client_integration/home/data_streams_tab.helpers'; + +describe('A11y Indices tab', () => { + let testBed: IndicesTestBed; + let httpSetup: ReturnType['httpSetup']; + let httpRequestsMockHelpers: ReturnType['httpRequestsMockHelpers']; + + beforeEach(() => { + const mockEnvironment = setupEnvironment(); + httpRequestsMockHelpers = mockEnvironment.httpRequestsMockHelpers; + httpSetup = mockEnvironment.httpSetup; + }); + + it('when there are no indices', async () => { + httpRequestsMockHelpers.setLoadIndicesResponse([]); + await act(async () => { + testBed = await setup(httpSetup); + }); + const { component } = testBed; + component.update(); + // this is expected to fail and needs to be updated when EUI 52.0.0 is available in Kibana + // await expectToBeAccessible(component); + // until then check that only 1 expected violation is found + const violations = await getA11yViolations(component); + expect(violations).toHaveLength(1); + const { id } = violations[0]; + expect(id).toEqual('aria-allowed-attr'); + }); + + it('when there are indices', async () => { + httpRequestsMockHelpers.setLoadIndicesResponse([ + createNonDataStreamIndex('non-data-stream-test-index'), + createDataStreamBackingIndex('data-stream-test-index', 'test-data-stream'), + ]); + await act(async () => { + testBed = await setup(httpSetup); + }); + const { component } = testBed; + component.update(); + // this is expected to fail and needs to be updated when EUI 52.0.0 is available in Kibana + // await expectToBeAccessible(component); + // until then check that only 1 expected violation is found + const violations = await getA11yViolations(component); + expect(violations).toHaveLength(1); + const { id } = violations[0]; + expect(id).toEqual('aria-allowed-attr'); + }); + + describe('index details flyout', () => { + beforeEach(async () => { + httpRequestsMockHelpers.setLoadIndicesResponse([ + createNonDataStreamIndex('non-data-stream-test-index'), + ]); + httpRequestsMockHelpers.setLoadIndexSettingsResponse(indexSettings); + httpRequestsMockHelpers.setLoadIndexMappingResponse(indexMappings); + httpRequestsMockHelpers.setLoadIndexStatsResponse(indexStats); + await act(async () => { + testBed = await setup(httpSetup); + }); + const { component, find } = testBed; + component.update(); + find('indexTableIndexNameLink').at(0).simulate('click'); + component.update(); + }); + + it('summary tab', async () => { + const { component, find } = testBed; + expect(find('detailPanelTabSelected').text()).toEqual('Summary'); + // this is expected to fail and needs to be updated when EUI 52.0.0 is available in Kibana + // await expectToBeAccessible(component); + // until then check that only 1 expected violation is found + const violations = await getA11yViolations(component); + expect(violations).toHaveLength(1); + const { id } = violations[0]; + expect(id).toEqual('aria-allowed-attr'); + }); + ['settings', 'mappings', 'stats'].forEach((tab) => { + it(`${tab} tab`, async () => { + const { component, find, actions } = testBed; + await actions.selectIndexDetailsTab(tab as 'settings'); + expect(find('detailPanelTabSelected').text().toLowerCase()).toEqual(tab); + // this is expected to fail and needs to be updated when EUI 52.0.0 is available in Kibana + // await expectToBeAccessible(component); + // until then check that only 1 expected violation is found + const violations = await getA11yViolations(component); + expect(violations).toHaveLength(1); + const { id } = violations[0]; + expect(id).toEqual('aria-allowed-attr'); + }); + }); + + it('edit settings tab', async () => { + const { component, find, actions } = testBed; + await actions.selectIndexDetailsTab('edit_settings'); + expect(find('detailPanelTabSelected').text()).toEqual('Edit settings'); + // this is expected to fail and needs to be updated when EUI 52.0.0 is available in Kibana + // await expectToBeAccessible(component); + // until then check that only 1 expected violation is found + const violations = await getA11yViolations(component); + expect(violations).toHaveLength(1); + const { id } = violations[0]; + expect(id).toEqual('aria-allowed-attr'); + }); + }); +}); diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/fixtures.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/fixtures.ts new file mode 100644 index 0000000000000..9f2423b1056f8 --- /dev/null +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/fixtures.ts @@ -0,0 +1,47 @@ +/* + * 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 indexSettings = { + settings: { index: { number_of_shards: '1' } }, + defaults: { index: { flush_after_merge: '512mb' } }, +}; + +export const indexMappings = { + mappings: { + dynamic: 'strict', + properties: { + '@timestamp': { + type: 'date', + }, + }, + }, +}; + +export const indexStats = { + _shards: { + total: 1, + successful: 1, + failed: 0, + }, + stats: { + uuid: 'test-uuid', + health: 'green', + status: 'open', + primaries: { + docs: { + count: 0, + deleted: 0, + }, + }, + total: { + docs: { + count: 0, + deleted: 0, + }, + }, + }, +}; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts index 4726286319e52..2be3d9c9460cf 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/http_requests.ts @@ -94,11 +94,14 @@ const registerHttpRequestMockHelpers = ( const setCreateTemplateResponse = (response?: HttpResponse, error?: ResponseError) => mockResponse('POST', `${API_BASE_PATH}/index_templates`, response, error); - const setUpdateTemplateResponse = ( - templateId: string, - response?: HttpResponse, - error?: ResponseError - ) => mockResponse('PUT', `${API_BASE_PATH}/index_templates/${templateId}`, response, error); + const setLoadIndexSettingsResponse = (response?: HttpResponse, error?: ResponseError) => + mockResponse('GET', `${API_BASE_PATH}/settings/:name`, response, error); + + const setLoadIndexMappingResponse = (response?: HttpResponse, error?: ResponseError) => + mockResponse('GET', `${API_BASE_PATH}/mapping/:name`, response, error); + + const setLoadIndexStatsResponse = (response?: HttpResponse, error?: ResponseError) => + mockResponse('GET', `${API_BASE_PATH}/stats/:name`, response, error); const setUpdateIndexSettingsResponse = ( indexName: string, @@ -128,7 +131,9 @@ const registerHttpRequestMockHelpers = ( setDeleteTemplateResponse, setLoadTemplateResponse, setCreateTemplateResponse, - setUpdateTemplateResponse, + setLoadIndexSettingsResponse, + setLoadIndexMappingResponse, + setLoadIndexStatsResponse, setUpdateIndexSettingsResponse, setSimulateTemplateResponse, setLoadComponentTemplatesResponse, diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts index ba2dea966d8cb..1fad428342482 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/index.ts @@ -18,3 +18,5 @@ export { } from './setup_environment'; export type { TestSubjects } from './test_subjects'; + +export * from './fixtures'; diff --git a/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts b/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts index f7066fbeda95e..2574594c7fcf8 100644 --- a/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts +++ b/x-pack/plugins/index_management/__jest__/client_integration/helpers/test_subjects.ts @@ -62,4 +62,5 @@ export type TestSubjects = | 'unfreezeIndexMenuButton' | 'updateEditIndexSettingsButton' | 'updateIndexSettingsErrorCallout' - | 'viewButton'; + | 'viewButton' + | 'detailPanelTabSelected'; diff --git a/yarn.lock b/yarn.lock index 6814b5463143e..5180f8fbbc6b8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5826,6 +5826,14 @@ dependencies: "@types/istanbul-lib-report" "*" +"@types/jest-axe@^3.5.3": + version "3.5.3" + resolved "https://registry.yarnpkg.com/@types/jest-axe/-/jest-axe-3.5.3.tgz#5af918553388aa0a448af75603b44093985778c6" + integrity sha512-ad9qI9f+00N8IlOuGh6dnZ6o0BDdV9VhGfTUr1zCejsPvOfZd6eohffe4JYxUoUuRYEftyMcaJ6Ux4+MsOpGHg== + dependencies: + "@types/jest" "*" + axe-core "^3.5.5" + "@types/jest-specific-snapshot@^0.5.3", "@types/jest-specific-snapshot@^0.5.5": version "0.5.5" resolved "https://registry.yarnpkg.com/@types/jest-specific-snapshot/-/jest-specific-snapshot-0.5.5.tgz#47ce738870be99898ed6d7b08dbf0240c74ae553" @@ -8447,6 +8455,16 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ== +axe-core@4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.2.1.tgz#2e50bcf10ee5b819014f6e342e41e45096239e34" + integrity sha512-evY7DN8qSIbsW2H/TWQ1bX3sXN1d4MNb5Vb4n7BzPuCwRHdkZ1H2eNLuSh73EoQqkGKUtju2G2HCcjCfhvZIAA== + +axe-core@^3.5.5: + version "3.5.6" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-3.5.6.tgz#e762a90d7f6dbd244ceacb4e72760ff8aad521b5" + integrity sha512-LEUDjgmdJoA3LqklSTwKYqkjcZ4HKc4ddIYGSAiSkr46NTjzg2L9RNB+lekO9P7Dlpa87+hBtzc2Fzn/+GUWMQ== + axe-core@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.0.2.tgz#c7cf7378378a51fcd272d3c09668002a4990b1cb" @@ -9752,6 +9770,14 @@ chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4. escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@4.1.0, chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chalk@4.1.2, chalk@^4.1.1, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -9779,14 +9805,6 @@ chalk@^3.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^4.0.0, chalk@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" - integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - chalk@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174" @@ -12376,6 +12394,11 @@ diff-sequences@^27.0.6: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.0.6.tgz#3305cb2e55a033924054695cc66019fd7f8e5723" integrity sha512-ag6wfpBFyNXZ0p8pcuIDS//D8H062ZQJ3fzYxjpmeKjnz8W4pekL3AI8VohmyZmsWW2PWaHgjsmqR6L13101VQ== +diff-sequences@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327" + integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ== + diff@5.0.0, diff@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" @@ -17573,6 +17596,16 @@ jake@^10.6.1: filelist "^1.0.1" minimatch "^3.0.4" +jest-axe@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/jest-axe/-/jest-axe-5.0.1.tgz#26c43643b2e5f2bd4900c1ab36f8283635957a6e" + integrity sha512-MMOWA6gT4pcZGbTLS8ZEqABH08Lnj5bInfLPpn9ADWX2wFF++odbbh8csmSfkwKjHaioVPzlCtIypAtxFDx/rw== + dependencies: + axe-core "4.2.1" + chalk "4.1.0" + jest-matcher-utils "27.0.2" + lodash.merge "4.6.2" + jest-canvas-mock@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/jest-canvas-mock/-/jest-canvas-mock-2.3.1.tgz#9535d14bc18ccf1493be36ac37dd349928387826" @@ -17680,6 +17713,16 @@ jest-diff@^26.0.0, jest-diff@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-diff@^27.0.2: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.5.1.tgz#a07f5011ac9e6643cf8a95a462b7b1ecf6680def" + integrity sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw== + dependencies: + chalk "^4.0.0" + diff-sequences "^27.5.1" + jest-get-type "^27.5.1" + pretty-format "^27.5.1" + jest-diff@^27.2.0: version "27.2.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-27.2.0.tgz#bda761c360f751bab1e7a2fe2fc2b0a35ce8518c" @@ -17752,6 +17795,11 @@ jest-get-type@^26.3.0: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== +jest-get-type@^27.0.1, jest-get-type@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.5.1.tgz#3cd613c507b0f7ace013df407a1c1cd578bcb4f1" + integrity sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw== + jest-get-type@^27.0.6: version "27.0.6" resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-27.0.6.tgz#0eb5c7f755854279ce9b68a9f1a4122f69047cfe" @@ -17810,6 +17858,16 @@ jest-leak-detector@^26.6.2: jest-get-type "^26.3.0" pretty-format "^26.6.2" +jest-matcher-utils@27.0.2: + version "27.0.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-27.0.2.tgz#f14c060605a95a466cdc759acc546c6f4cbfc4f0" + integrity sha512-Qczi5xnTNjkhcIB0Yy75Txt+Ez51xdhOxsukN7awzq2auZQGPHcQrJ623PZj0ECDEMOk2soxWx05EXdXGd1CbA== + dependencies: + chalk "^4.0.0" + jest-diff "^27.0.2" + jest-get-type "^27.0.1" + pretty-format "^27.0.2" + jest-matcher-utils@^24.9.0: version "24.9.0" resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" @@ -19162,7 +19220,7 @@ lodash.memoize@~3.0.3: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-3.0.4.tgz#2dcbd2c287cbc0a55cc42328bd0c736150d53e3f" integrity sha1-LcvSwofLwKVcxCMovQxzYVDVPj8= -lodash.merge@^4.6.2: +lodash.merge@4.6.2, lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== @@ -22889,6 +22947,15 @@ pretty-format@^26.0.0, pretty-format@^26.6.2: ansi-styles "^4.0.0" react-is "^17.0.1" +pretty-format@^27.0.2, pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + pretty-format@^27.2.0: version "27.2.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.2.0.tgz#ee37a94ce2a79765791a8649ae374d468c18ef19" From 2dcdbbe658e12a713280c7fcb8a8956a672fde90 Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Tue, 29 Mar 2022 11:58:26 +0300 Subject: [PATCH 07/31] [XY] `system_palette` and `palette` support. (#128053) * Added support of `system_palette` and `palette` types at the `dataLayer` `palette` arg. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Marta Bondyra --- .../expression_functions/data_layer_config.ts | 4 +- .../__snapshots__/to_expression.test.ts.snap | 16 +++++++ .../public/xy_visualization/to_expression.ts | 46 ++++++++++--------- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/src/plugins/chart_expressions/expression_xy/common/expression_functions/data_layer_config.ts b/src/plugins/chart_expressions/expression_xy/common/expression_functions/data_layer_config.ts index 3aac992d674d9..e9ffa0f41f49f 100644 --- a/src/plugins/chart_expressions/expression_xy/common/expression_functions/data_layer_config.ts +++ b/src/plugins/chart_expressions/expression_xy/common/expression_functions/data_layer_config.ts @@ -106,11 +106,11 @@ export const dataLayerConfigFunction: ExpressionFunctionDefinition< }), }, palette: { - default: `{theme "palette" default={system_palette name="default"} }`, + types: ['palette', 'system_palette'], help: i18n.translate('expressionXY.dataLayer.palette.help', { defaultMessage: 'Palette', }), - types: ['palette'], + default: '{palette}', }, }, fn(input, args) { diff --git a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap index 27cc383834049..256df38ffa5b3 100644 --- a/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap +++ b/x-pack/plugins/lens/public/xy_visualization/__snapshots__/to_expression.test.ts.snap @@ -113,6 +113,22 @@ Object { "layerId": Array [ "first", ], + "palette": Array [ + Object { + "chain": Array [ + Object { + "arguments": Object { + "name": Array [ + "default", + ], + }, + "function": "system_palette", + "type": "function", + }, + ], + "type": "expression", + }, + ], "seriesType": Array [ "area", ], diff --git a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts index ec9093a999c84..86ae7e0bc328e 100644 --- a/x-pack/plugins/lens/public/xy_visualization/to_expression.ts +++ b/x-pack/plugins/lens/public/xy_visualization/to_expression.ts @@ -480,29 +480,31 @@ const dataLayerToExpression = ( seriesType: [layer.seriesType], accessors: layer.accessors, columnToLabel: [JSON.stringify(columnToLabel)], - ...(layer.palette - ? { - palette: [ - { - type: 'expression', - chain: [ - { - type: 'function', - function: 'theme', - arguments: { - variable: ['palette'], - default: [ - paletteService - .get(layer.palette.name) - .toExpression(layer.palette.params), - ], - }, + palette: [ + { + type: 'expression', + chain: [ + layer.palette + ? { + type: 'function', + function: 'theme', + arguments: { + variable: ['palette'], + default: [ + paletteService.get(layer.palette.name).toExpression(layer.palette.params), + ], }, - ], - }, - ], - } - : {}), + } + : { + type: 'function', + function: 'system_palette', + arguments: { + name: ['default'], + }, + }, + ], + }, + ], }, }, ], From 7cb72014aab9d5bb403c1b3507922c44c18acefa Mon Sep 17 00:00:00 2001 From: Thomas Watson Date: Tue, 29 Mar 2022 11:08:21 +0200 Subject: [PATCH 08/31] Bump @elastic/request-crypto from v2.0.0 to v2.0.1 (#128710) --- package.json | 3 +-- yarn.lock | 69 ++++++++++++++++++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/package.json b/package.json index 4eba243e30b8a..35edc14f01325 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,6 @@ "**/json-schema": "^0.4.0", "**/minimatch": "^3.1.2", "**/minimist": "^1.2.6", - "**/node-forge": "^1.3.0", "**/pdfkit/crypto-js": "4.0.0", "**/react-syntax-highlighter": "^15.3.1", "**/react-syntax-highlighter/**/highlight.js": "^10.4.1", @@ -114,7 +113,7 @@ "@elastic/node-crypto": "1.2.1", "@elastic/numeral": "^2.5.1", "@elastic/react-search-ui": "^1.6.0", - "@elastic/request-crypto": "2.0.0", + "@elastic/request-crypto": "2.0.1", "@elastic/safer-lodash-set": "link:bazel-bin/packages/elastic-safer-lodash-set", "@elastic/search-ui-app-search-connector": "^1.6.0", "@emotion/cache": "^11.4.0", diff --git a/yarn.lock b/yarn.lock index 5180f8fbbc6b8..ce7e815915a8b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1613,14 +1613,14 @@ "@elastic/react-search-ui-views" "1.6.0" "@elastic/search-ui" "1.6.0" -"@elastic/request-crypto@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@elastic/request-crypto/-/request-crypto-2.0.0.tgz#a3988be98ed63398c3d0177948c7ac2a857835bb" - integrity sha512-jIReBeHzgUKNsYwdhnTyLFSGHyLsJgQIIw+AMEnq1lcONA/uKG7hhFUK2Z8XxjJ86/oXt1TwJ4BIagZR3mzq7w== +"@elastic/request-crypto@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@elastic/request-crypto/-/request-crypto-2.0.1.tgz#88dc41e4bbba6764c323e1a820757607e2f4f720" + integrity sha512-ZFZ+CF1hb22+BLAe93D4Kc1EMPfVDKckd8SY6IHk/N4H1WUthQ9xXfPVx06r+pTkz62HliyQfXgLKFTQa+aSmw== dependencies: "@elastic/node-crypto" "1.1.1" - "@types/node-jose" "1.1.8" - node-jose "2.0.0" + "@types/node-jose" "1.1.10" + node-jose "2.1.0" "@elastic/safer-lodash-set@link:bazel-bin/packages/elastic-safer-lodash-set": version "0.0.0" @@ -6364,10 +6364,10 @@ dependencies: "@types/node" "*" -"@types/node-jose@1.1.8": - version "1.1.8" - resolved "https://registry.yarnpkg.com/@types/node-jose/-/node-jose-1.1.8.tgz#26b7ae96e3309acb426ea5393ff5d6a0c1c38625" - integrity sha512-AFcArbplUaO+DqGVEPaiz/guw3uUA+dRHjaj26EEDF0DmTEPUd3dEdfdJMUx4kD65EAR3TnI1iHIcb31+Ko87Q== +"@types/node-jose@1.1.10": + version "1.1.10" + resolved "https://registry.yarnpkg.com/@types/node-jose/-/node-jose-1.1.10.tgz#1fc559b63e665f27acedbcb91601e2fee256fad0" + integrity sha512-7L0ucJTugW4x/sYpQ+c5IudAwr0pFuxDVnZLpHKWpff7p1lVa3wTuNvnrzFBNeLojE+UY0cVCwNGXLxXsMIrzw== dependencies: "@types/node" "*" @@ -9432,6 +9432,14 @@ buffer@^5.2.1: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + buffer@~5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" @@ -16401,7 +16409,7 @@ ieee754@^1.1.12, ieee754@^1.1.4: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -19380,6 +19388,11 @@ long@^4.0.0: resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== +long@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/long/-/long-5.2.0.tgz#2696dadf4b4da2ce3f6f6b89186085d94d52fd61" + integrity sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w== + longest-streak@^2.0.0, longest-streak@^2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" @@ -20768,7 +20781,12 @@ node-fetch@2.6.1, node-fetch@^1.0.1, node-fetch@^2.3.0, node-fetch@^2.6.1, node- dependencies: whatwg-url "^5.0.0" -node-forge@^0.10.0, node-forge@^1.3.0: +node-forge@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" + integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== + +node-forge@^1.2.1, node-forge@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.0.tgz#37a874ea723855f37db091e6c186e5b67a01d4b2" integrity sha512-08ARB91bUi6zNKzVmaj3QO7cr397uiDT2nJ63cHjyNtCTWIgvS47j3eT0WfzUwS9+6Z5YshRaoasFkXCKrIYbA== @@ -20815,20 +20833,20 @@ node-int64@^0.4.0: resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= -node-jose@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/node-jose/-/node-jose-2.0.0.tgz#541c6b52c387a3f18fc06cd502baad759af9c470" - integrity sha512-j8zoFze1gijl8+DK/dSXXqX7+o2lMYv1XS+ptnXgGV/eloQaqq1YjNtieepbKs9jBS4WTnMOqyKSaQuunJzx0A== +node-jose@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/node-jose/-/node-jose-2.1.0.tgz#a2d12a7ff2d386f23979c1bf77f939449ce073d8" + integrity sha512-Zmm8vFPJabphGBc5Wz1/LUMPS+1cynqw16RIhgVNQMEI2yEQrvl7Gx2EwN9GhP8tkm8f7SH53K2nIx8TeNTIdg== dependencies: base64url "^3.0.1" - buffer "^5.5.0" + buffer "^6.0.3" es6-promise "^4.2.8" - lodash "^4.17.15" - long "^4.0.0" - node-forge "^0.10.0" - pako "^1.0.11" + lodash "^4.17.21" + long "^5.2.0" + node-forge "^1.2.1" + pako "^2.0.4" process "^0.11.10" - uuid "^3.3.3" + uuid "^8.3.2" node-libs-browser@^2.2.1: version "2.2.1" @@ -21744,11 +21762,16 @@ pako@^0.2.5: resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75" integrity sha1-8/dSL073gjSNqBYbrZ7P1Rv4OnU= -pako@^1.0.11, pako@^1.0.3, pako@^1.0.5, pako@~1.0.2, pako@~1.0.5: +pako@^1.0.3, pako@^1.0.5, pako@~1.0.2, pako@~1.0.5: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== +pako@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.4.tgz#6cebc4bbb0b6c73b0d5b8d7e8476e2b2fbea576d" + integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg== + papaparse@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.2.0.tgz#97976a1b135c46612773029153dc64995caa3b7b" From 23586d2e4f0039c5a95f70a8e51c01a1ae1485b7 Mon Sep 17 00:00:00 2001 From: Jordan <51442161+JordanSh@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:32:19 +0300 Subject: [PATCH 09/31] CSP Viewing states (#128215) --- .../cloud_security_posture/common/types.ts | 2 +- .../public/common/api/index.ts | 2 +- .../api/use_cis_kubernetes_integration.tsx | 31 +++ ...s => use_compliance_dashboard_data_api.ts} | 6 +- .../public/components/chart_panel.tsx | 4 +- .../components/csp_page_template.test.tsx | 258 ++++++++++++++++++ .../public/components/csp_page_template.tsx | 202 ++++++++++++++ .../public/components/page_template.test.tsx | 158 ----------- .../public/components/page_template.tsx | 117 -------- .../public/components/translations.ts | 41 ++- .../public/components/unknown_route.tsx | 2 +- .../pages/benchmarks/benchmarks.test.tsx | 7 + .../public/pages/benchmarks/benchmarks.tsx | 5 +- .../compliance_charts/risks_table.tsx | 6 +- .../compliance_dashboard.tsx | 53 ++-- .../dashboard_sections/benchmarks_section.tsx | 42 +-- .../dashboard_sections/summary_section.tsx | 25 +- .../compliance_dashboard/translations.ts | 15 + .../public/pages/findings/findings.test.tsx | 5 + .../public/pages/findings/findings.tsx | 11 +- .../public/pages/rules/index.tsx | 17 +- .../public/pages/rules/rules.test.tsx | 7 + .../public/test/fixtures/react_query.ts | 8 +- .../compliance_dashboard.ts | 4 +- .../compliance_dashboard/get_clusters.test.ts | 2 +- .../compliance_dashboard/get_clusters.ts | 8 +- .../get_resources_types.test.ts | 2 +- .../get_resources_types.ts | 8 +- .../compliance_dashboard/get_stats.test.ts | 2 +- .../routes/compliance_dashboard/get_stats.ts | 8 +- 30 files changed, 646 insertions(+), 412 deletions(-) create mode 100644 x-pack/plugins/cloud_security_posture/public/common/api/use_cis_kubernetes_integration.tsx rename x-pack/plugins/cloud_security_posture/public/common/api/{use_cloud_posture_stats_api.ts => use_compliance_dashboard_data_api.ts} (71%) create mode 100644 x-pack/plugins/cloud_security_posture/public/components/csp_page_template.test.tsx create mode 100644 x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx delete mode 100644 x-pack/plugins/cloud_security_posture/public/components/page_template.test.tsx delete mode 100644 x-pack/plugins/cloud_security_posture/public/components/page_template.tsx diff --git a/x-pack/plugins/cloud_security_posture/common/types.ts b/x-pack/plugins/cloud_security_posture/common/types.ts index ca01d1ad927cd..b414b49ef30d3 100644 --- a/x-pack/plugins/cloud_security_posture/common/types.ts +++ b/x-pack/plugins/cloud_security_posture/common/types.ts @@ -35,7 +35,7 @@ export interface Cluster { resourcesTypes: ResourceType[]; } -export interface CloudPostureStats { +export interface ComplianceDashboardData { stats: Stats; resourcesTypes: ResourceType[]; clusters: Cluster[]; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/index.ts b/x-pack/plugins/cloud_security_posture/public/common/api/index.ts index 915881e2ab9b2..2468e095ff5f9 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/index.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/index.ts @@ -5,4 +5,4 @@ * 2.0. */ -export * from './use_cloud_posture_stats_api'; +export * from './use_compliance_dashboard_data_api'; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_cis_kubernetes_integration.tsx b/x-pack/plugins/cloud_security_posture/public/common/api/use_cis_kubernetes_integration.tsx new file mode 100644 index 0000000000000..09b77a20835f7 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_cis_kubernetes_integration.tsx @@ -0,0 +1,31 @@ +/* + * 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 { useQuery } from 'react-query'; +import { + epmRouteService, + type GetInfoResponse, + type DefaultPackagesInstallationError, +} from '../../../../fleet/common'; +import { CIS_KUBERNETES_PACKAGE_NAME } from '../../../common/constants'; +import { useKibana } from '../hooks/use_kibana'; + +export const CIS_KUBERNETES_INTEGRATION_VERSION = '0.0.1'; + +/** + * This hook will find our cis integration and return its PackageInfo + * */ +export const useCisKubernetesIntegration = () => { + const { http } = useKibana().services; + + return useQuery(['integrations'], () => + http.get( + epmRouteService.getInfoPath(CIS_KUBERNETES_PACKAGE_NAME, CIS_KUBERNETES_INTEGRATION_VERSION), + { query: { experimental: true } } + ) + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/common/api/use_cloud_posture_stats_api.ts b/x-pack/plugins/cloud_security_posture/public/common/api/use_compliance_dashboard_data_api.ts similarity index 71% rename from x-pack/plugins/cloud_security_posture/public/common/api/use_cloud_posture_stats_api.ts rename to x-pack/plugins/cloud_security_posture/public/common/api/use_compliance_dashboard_data_api.ts index c1cc4a61fd7ae..91bedbf83769d 100644 --- a/x-pack/plugins/cloud_security_posture/public/common/api/use_cloud_posture_stats_api.ts +++ b/x-pack/plugins/cloud_security_posture/public/common/api/use_compliance_dashboard_data_api.ts @@ -7,12 +7,12 @@ import { useQuery } from 'react-query'; import { useKibana } from '../../../../../../src/plugins/kibana_react/public'; -import { CloudPostureStats } from '../../../common/types'; +import { ComplianceDashboardData } from '../../../common/types'; import { STATS_ROUTE_PATH } from '../../../common/constants'; const getStatsKey = 'csp_dashboard_stats'; -export const useCloudPostureStatsApi = () => { +export const useComplianceDashboardDataApi = () => { const { http } = useKibana().services; - return useQuery([getStatsKey], () => http!.get(STATS_ROUTE_PATH)); + return useQuery([getStatsKey], () => http!.get(STATS_ROUTE_PATH)); }; diff --git a/x-pack/plugins/cloud_security_posture/public/components/chart_panel.tsx b/x-pack/plugins/cloud_security_posture/public/components/chart_panel.tsx index 2b0882d0916e6..54592880f47ff 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/chart_panel.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/chart_panel.tsx @@ -19,8 +19,8 @@ import { CHART_PANEL_TEST_SUBJECTS } from './constants'; interface ChartPanelProps { title?: string; hasBorder?: boolean; - isLoading: boolean; - isError: boolean; + isLoading?: boolean; + isError?: boolean; } const Loading = () => ( diff --git a/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.test.tsx new file mode 100644 index 0000000000000..ef097f224ab5f --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.test.tsx @@ -0,0 +1,258 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { type ComponentProps } from 'react'; +import { render, screen } from '@testing-library/react'; +import Chance from 'chance'; +import { coreMock } from '../../../../../src/core/public/mocks'; +import { createNavigationItemFixture } from '../test/fixtures/navigation_item'; +import { createReactQueryResponse } from '../test/fixtures/react_query'; +import { TestProvider } from '../test/test_provider'; +import { CspPageTemplate, getSideNavItems, isCommonError } from './csp_page_template'; +import { LOADING, PACKAGE_NOT_INSTALLED_TEXT, DEFAULT_NO_DATA_TEXT } from './translations'; +import { useCisKubernetesIntegration } from '../common/api/use_cis_kubernetes_integration'; +import { UseQueryResult } from 'react-query'; + +const chance = new Chance(); + +// Synchronized to the error message in the formatted message in `csp_page_template.tsx` +const ERROR_LOADING_DATA_DEFAULT_MESSAGE = "We couldn't fetch your cloud security posture data"; +const packageNotInstalledUniqueTexts = [ + PACKAGE_NOT_INSTALLED_TEXT.PAGE_TITLE, + PACKAGE_NOT_INSTALLED_TEXT.DESCRIPTION, +]; + +jest.mock('../common/api/use_cis_kubernetes_integration'); + +describe('getSideNavItems', () => { + it('maps navigation items to side navigation items', () => { + const navigationItem = createNavigationItemFixture(); + const id = chance.word(); + const sideNavItems = getSideNavItems({ [id]: navigationItem }); + + expect(sideNavItems).toHaveLength(1); + expect(sideNavItems[0]).toMatchObject({ + id, + name: navigationItem.name, + renderItem: expect.any(Function), + }); + }); + + it('does not map disabled navigation items to side navigation items', () => { + const navigationItem = createNavigationItemFixture({ disabled: true }); + const id = chance.word(); + const sideNavItems = getSideNavItems({ [id]: navigationItem }); + expect(sideNavItems).toHaveLength(0); + }); +}); + +describe('', () => { + beforeEach(() => { + jest.resetAllMocks(); + // if package installation status is 'not_installed', CspPageTemplate will render a noDataConfig prompt + (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ + data: { item: { status: 'installed' } }, + })); + }); + + const renderCspPageTemplate = (props: ComponentProps = {}) => { + const mockCore = coreMock.createStart(); + + render( + + + + ); + }; + + it('renders children if integration is installed', () => { + const children = chance.sentence(); + renderCspPageTemplate({ children }); + + expect(screen.getByText(children)).toBeInTheDocument(); + expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); + expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); + packageNotInstalledUniqueTexts.forEach((text) => + expect(screen.queryByText(text)).not.toBeInTheDocument() + ); + }); + + it('renders integrations installation prompt if integration is not installed', () => { + (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ + isSuccess: true, + data: { item: { status: 'not_installed' } }, + })); + + const children = chance.sentence(); + renderCspPageTemplate({ children }); + + Object.values(PACKAGE_NOT_INSTALLED_TEXT).forEach((text) => + expect(screen.getByText(text)).toBeInTheDocument() + ); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); + expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); + }); + + it('renders default loading text when query isLoading', () => { + const query = createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCspPageTemplate({ children, query }); + + expect(screen.getByText(LOADING)).toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); + packageNotInstalledUniqueTexts.forEach((text) => + expect(screen.queryByText(text)).not.toBeInTheDocument() + ); + }); + + it('renders default error texts when query isError', () => { + const error = chance.sentence(); + const message = chance.sentence(); + const statusCode = chance.integer(); + + const query = createReactQueryResponse({ + status: 'error', + error: { + body: { + error, + message, + statusCode, + }, + }, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCspPageTemplate({ children, query }); + + [ERROR_LOADING_DATA_DEFAULT_MESSAGE, error, message, statusCode].forEach((text) => + expect(screen.getByText(text, { exact: false })).toBeInTheDocument() + ); + expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + packageNotInstalledUniqueTexts.forEach((text) => + expect(screen.queryByText(text)).not.toBeInTheDocument() + ); + }); + + it('prefers custom error render', () => { + const error = chance.sentence(); + const message = chance.sentence(); + const statusCode = chance.integer(); + + const query = createReactQueryResponse({ + status: 'error', + error: { + body: { + error, + message, + statusCode, + }, + }, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCspPageTemplate({ + children, + query, + errorRender: (err) =>
{isCommonError(err) && err.body.message}
, + }); + + expect(screen.getByText(message)).toBeInTheDocument(); + [ERROR_LOADING_DATA_DEFAULT_MESSAGE, error, statusCode].forEach((text) => + expect(screen.queryByText(text)).not.toBeInTheDocument() + ); + expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + packageNotInstalledUniqueTexts.forEach((text) => + expect(screen.queryByText(text)).not.toBeInTheDocument() + ); + }); + + it('prefers custom loading render', () => { + const loading = chance.sentence(); + + const query = createReactQueryResponse({ + status: 'loading', + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCspPageTemplate({ + children, + query, + loadingRender: () =>
{loading}
, + }); + + expect(screen.getByText(loading)).toBeInTheDocument(); + expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); + expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + packageNotInstalledUniqueTexts.forEach((text) => + expect(screen.queryByText(text)).not.toBeInTheDocument() + ); + }); + + it('renders noDataConfig prompt when query data is undefined', () => { + const query = createReactQueryResponse({ + status: 'success', + data: undefined, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCspPageTemplate({ children, query }); + + expect(screen.getByText(DEFAULT_NO_DATA_TEXT.PAGE_TITLE)).toBeInTheDocument(); + expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); + packageNotInstalledUniqueTexts.forEach((text) => + expect(screen.queryByText(text)).not.toBeInTheDocument() + ); + }); + + it('prefers custom noDataConfig prompt', () => { + const pageTitle = chance.sentence(); + const solution = chance.sentence(); + const docsLink = chance.sentence(); + + const query = createReactQueryResponse({ + status: 'success', + data: undefined, + }) as unknown as UseQueryResult; + + const children = chance.sentence(); + renderCspPageTemplate({ + children, + query, + noDataConfig: { pageTitle, solution, docsLink, actions: {} }, + }); + + expect(screen.getByText(pageTitle)).toBeInTheDocument(); + expect(screen.getByText(solution, { exact: false })).toBeInTheDocument(); + expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); + expect(screen.queryByText(children)).not.toBeInTheDocument(); + expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); + packageNotInstalledUniqueTexts.forEach((text) => + expect(screen.queryByText(text)).not.toBeInTheDocument() + ); + }); +}); diff --git a/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx b/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx new file mode 100644 index 0000000000000..8d1d96f2cb9f7 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/components/csp_page_template.tsx @@ -0,0 +1,202 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import type { UseQueryResult } from 'react-query'; +import { NavLink } from 'react-router-dom'; +import { EuiEmptyPrompt, EuiErrorBoundary, EuiTitle } from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { + KibanaPageTemplate, + type KibanaPageTemplateProps, +} from '../../../../../src/plugins/kibana_react/public'; +import { allNavigationItems } from '../common/navigation/constants'; +import type { CspNavigationItem } from '../common/navigation/types'; +import { CLOUD_SECURITY_POSTURE } from '../common/translations'; +import { CspLoadingState } from './csp_loading_state'; +import { DEFAULT_NO_DATA_TEXT, LOADING, PACKAGE_NOT_INSTALLED_TEXT } from './translations'; +import { useCisKubernetesIntegration } from '../common/api/use_cis_kubernetes_integration'; +import { useCISIntegrationLink } from '../common/navigation/use_navigate_to_cis_integration'; + +export interface CommonError { + body: { + error: string; + message: string; + statusCode: number; + }; +} + +export const isCommonError = (x: any): x is CommonError => { + if (!('body' in x)) return false; + + const { + body: { error, message, statusCode }, + } = x; + + return !!(error && message && statusCode); +}; + +const activeItemStyle = { fontWeight: 700 }; + +export const getSideNavItems = ( + navigationItems: Record +): NonNullable['items'] => + Object.entries(navigationItems) + .filter(([_, navigationItem]) => !navigationItem.disabled) + .map(([id, navigationItem]) => ({ + id, + name: navigationItem.name, + renderItem: () => ( + + {navigationItem.name} + + ), + })); + +const DEFAULT_PAGE_PROPS: KibanaPageTemplateProps = { + solutionNav: { + name: CLOUD_SECURITY_POSTURE, + items: getSideNavItems({ + dashboard: allNavigationItems.dashboard, + findings: allNavigationItems.findings, + benchmark: allNavigationItems.benchmarks, + }), + }, + restrictWidth: false, +}; + +export const DEFAULT_NO_DATA_CONFIG: KibanaPageTemplateProps['noDataConfig'] = { + pageTitle: DEFAULT_NO_DATA_TEXT.PAGE_TITLE, + solution: DEFAULT_NO_DATA_TEXT.SOLUTION, + // TODO: Add real docs link once we have it + docsLink: 'https://www.elastic.co/guide/index.html', + logo: 'logoSecurity', + actions: {}, +}; + +const getPackageNotInstalledNoDataConfig = ( + cisIntegrationLink: string +): KibanaPageTemplateProps['noDataConfig'] => ({ + pageTitle: PACKAGE_NOT_INSTALLED_TEXT.PAGE_TITLE, + solution: PACKAGE_NOT_INSTALLED_TEXT.SOLUTION, + // TODO: Add real docs link once we have it + docsLink: 'https://www.elastic.co/guide/index.html', + logo: 'logoSecurity', + actions: { + elasticAgent: { + href: cisIntegrationLink, + title: PACKAGE_NOT_INSTALLED_TEXT.BUTTON_TITLE, + description: PACKAGE_NOT_INSTALLED_TEXT.DESCRIPTION, + }, + }, +}); + +const DefaultLoading = () => {LOADING}; + +const DefaultError = (error: unknown) => ( + + +

+ +

+
+ {isCommonError(error) && ( + <> + +
+ +
+
+ +
+ +
+
+ + )} + + } + /> +); + +export const CspPageTemplate = ({ + query, + children, + loadingRender = DefaultLoading, + errorRender = DefaultError, + ...kibanaPageTemplateProps +}: KibanaPageTemplateProps & { + loadingRender?: () => React.ReactNode; + errorRender?: (error: TError) => React.ReactNode; + query?: UseQueryResult; +}) => { + const cisKubernetesPackageInfo = useCisKubernetesIntegration(); + const cisIntegrationLink = useCISIntegrationLink(); + + const getNoDataConfig = (): KibanaPageTemplateProps['noDataConfig'] => { + if ( + cisKubernetesPackageInfo?.isSuccess && + cisKubernetesPackageInfo.data.item.status === 'not_installed' + ) { + return getPackageNotInstalledNoDataConfig(cisIntegrationLink); + } + + // when query was successful, but data is undefined + if (query?.isSuccess && !query?.data) { + return kibanaPageTemplateProps.noDataConfig || DEFAULT_NO_DATA_CONFIG; + } + + // when the consumer didn't pass a query, most likely to handle the render on his own + if (!query) return kibanaPageTemplateProps.noDataConfig; + }; + + const getTemplate = (): KibanaPageTemplateProps['template'] => { + if (query?.isLoading || query?.isError) return 'centeredContent'; + + return kibanaPageTemplateProps.template || 'default'; + }; + + const render = () => { + if (query?.isLoading) return loadingRender(); + if (query?.isError) return errorRender(query.error); + if (query?.isSuccess) return children; + + return children; + }; + + return ( + + + {cisKubernetesPackageInfo?.data?.item.status === 'installed' && render()} + + + ); +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/page_template.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/page_template.test.tsx deleted file mode 100644 index 1c367cd5c57f0..0000000000000 --- a/x-pack/plugins/cloud_security_posture/public/components/page_template.test.tsx +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React, { type ComponentProps } from 'react'; -import { render, screen } from '@testing-library/react'; -import Chance from 'chance'; -import { coreMock } from '../../../../../src/core/public/mocks'; -import { createStubDataView } from '../../../../../src/plugins/data_views/public/data_views/data_view.stub'; -import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../common/constants'; -import { useKubebeatDataView } from '../common/api/use_kubebeat_data_view'; -import { createNavigationItemFixture } from '../test/fixtures/navigation_item'; -import { createReactQueryResponse } from '../test/fixtures/react_query'; -import { TestProvider } from '../test/test_provider'; -import { CspPageTemplate, getSideNavItems } from './page_template'; -import { - LOADING, - NO_DATA_CONFIG_BUTTON, - NO_DATA_CONFIG_DESCRIPTION, - NO_DATA_CONFIG_TITLE, -} from './translations'; - -const chance = new Chance(); - -const BLANK_PAGE_GRAPHIC_TEXTS = [ - NO_DATA_CONFIG_TITLE, - NO_DATA_CONFIG_DESCRIPTION, - NO_DATA_CONFIG_BUTTON, -]; - -// Synchronized to the error message in the formatted message in `page_template.tsx` -const ERROR_LOADING_DATA_DEFAULT_MESSAGE = "We couldn't fetch your cloud security posture data"; - -jest.mock('../common/api/use_kubebeat_data_view'); - -describe('getSideNavItems', () => { - it('maps navigation items to side navigation items', () => { - const navigationItem = createNavigationItemFixture(); - const id = chance.word(); - const sideNavItems = getSideNavItems({ [id]: navigationItem }); - - expect(sideNavItems).toHaveLength(1); - expect(sideNavItems[0]).toMatchObject({ - id, - name: navigationItem.name, - renderItem: expect.any(Function), - }); - }); - - it('does not map disabled navigation items to side navigation items', () => { - const navigationItem = createNavigationItemFixture({ disabled: true }); - const id = chance.word(); - const sideNavItems = getSideNavItems({ [id]: navigationItem }); - expect(sideNavItems).toHaveLength(0); - }); -}); - -describe('', () => { - beforeEach(() => { - jest.resetAllMocks(); - }); - - const renderCspPageTemplate = (props: ComponentProps = {}) => { - const mockCore = coreMock.createStart(); - - render( - - - - ); - }; - - it('renders children when data view is found', () => { - (useKubebeatDataView as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: createStubDataView({ - spec: { - id: CSP_KUBEBEAT_INDEX_PATTERN, - }, - }), - }) - ); - - const children = chance.sentence(); - renderCspPageTemplate({ children }); - - expect(screen.getByText(children)).toBeInTheDocument(); - expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); - expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); - BLANK_PAGE_GRAPHIC_TEXTS.forEach((blankPageGraphicText) => - expect(screen.queryByText(blankPageGraphicText)).not.toBeInTheDocument() - ); - }); - - it('renders loading text when data view is loading', () => { - (useKubebeatDataView as jest.Mock).mockImplementation(() => - createReactQueryResponse({ status: 'loading' }) - ); - - const children = chance.sentence(); - renderCspPageTemplate({ children }); - - expect(screen.getByText(LOADING)).toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); - BLANK_PAGE_GRAPHIC_TEXTS.forEach((blankPageGraphicText) => - expect(screen.queryByText(blankPageGraphicText)).not.toBeInTheDocument() - ); - }); - - it('renders an error view when data view fetching has an error', () => { - (useKubebeatDataView as jest.Mock).mockImplementation(() => - createReactQueryResponse({ status: 'error', error: new Error('') }) - ); - - const children = chance.sentence(); - renderCspPageTemplate({ children }); - - expect(screen.getByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).toBeInTheDocument(); - expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - BLANK_PAGE_GRAPHIC_TEXTS.forEach((blankPageGraphicText) => - expect(screen.queryByText(blankPageGraphicText)).not.toBeInTheDocument() - ); - }); - - it('renders the blank page graphic when data view is missing', () => { - (useKubebeatDataView as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: undefined, - }) - ); - - const children = chance.sentence(); - renderCspPageTemplate({ children }); - - BLANK_PAGE_GRAPHIC_TEXTS.forEach((text) => expect(screen.getByText(text)).toBeInTheDocument()); - expect(screen.queryByText(ERROR_LOADING_DATA_DEFAULT_MESSAGE)).not.toBeInTheDocument(); - expect(screen.queryByText(LOADING)).not.toBeInTheDocument(); - expect(screen.queryByText(children)).not.toBeInTheDocument(); - }); -}); diff --git a/x-pack/plugins/cloud_security_posture/public/components/page_template.tsx b/x-pack/plugins/cloud_security_posture/public/components/page_template.tsx deleted file mode 100644 index 45cae3f996e36..0000000000000 --- a/x-pack/plugins/cloud_security_posture/public/components/page_template.tsx +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import React from 'react'; -import { NavLink } from 'react-router-dom'; -import { EuiEmptyPrompt, EuiErrorBoundary, EuiTitle } from '@elastic/eui'; -import { FormattedMessage } from '@kbn/i18n-react'; -import { - KibanaPageTemplate, - type KibanaPageTemplateProps, -} from '../../../../../src/plugins/kibana_react/public'; -import { useKubebeatDataView } from '../common/api/use_kubebeat_data_view'; -import { allNavigationItems } from '../common/navigation/constants'; -import type { CspNavigationItem } from '../common/navigation/types'; -import { useCISIntegrationLink } from '../common/navigation/use_navigate_to_cis_integration'; -import { CLOUD_SECURITY_POSTURE } from '../common/translations'; -import { CspLoadingState } from './csp_loading_state'; -import { - LOADING, - NO_DATA_CONFIG_BUTTON, - NO_DATA_CONFIG_DESCRIPTION, - NO_DATA_CONFIG_SOLUTION_NAME, - NO_DATA_CONFIG_TITLE, -} from './translations'; - -const activeItemStyle = { fontWeight: 700 }; - -export const getSideNavItems = ( - navigationItems: Record -): NonNullable['items'] => - Object.entries(navigationItems) - .filter(([_, navigationItem]) => !navigationItem.disabled) - .map(([id, navigationItem]) => ({ - id, - name: navigationItem.name, - renderItem: () => ( - - {navigationItem.name} - - ), - })); - -const DEFAULT_PROPS: KibanaPageTemplateProps = { - solutionNav: { - name: CLOUD_SECURITY_POSTURE, - items: getSideNavItems({ - dashboard: allNavigationItems.dashboard, - findings: allNavigationItems.findings, - benchmark: allNavigationItems.benchmarks, - }), - }, - restrictWidth: false, -}; - -const getNoDataConfig = (cisIntegrationLink: string): KibanaPageTemplateProps['noDataConfig'] => ({ - pageTitle: NO_DATA_CONFIG_TITLE, - solution: NO_DATA_CONFIG_SOLUTION_NAME, - // TODO: Add real docs link once we have it - docsLink: 'https://www.elastic.co/guide/index.html', - logo: 'logoSecurity', - actions: { - elasticAgent: { - href: cisIntegrationLink, - title: NO_DATA_CONFIG_BUTTON, - description: NO_DATA_CONFIG_DESCRIPTION, - }, - }, -}); - -export const CspPageTemplate: React.FC = ({ children, ...props }) => { - // TODO: Consider using more sophisticated logic to find out if our integration is installed - const kubeBeatQuery = useKubebeatDataView(); - const cisIntegrationLink = useCISIntegrationLink(); - - let noDataConfig: KibanaPageTemplateProps['noDataConfig']; - if (kubeBeatQuery.status === 'success' && !kubeBeatQuery.data) { - noDataConfig = getNoDataConfig(cisIntegrationLink); - } - - let template: KibanaPageTemplateProps['template'] = 'default'; - if (kubeBeatQuery.status === 'error' || kubeBeatQuery.status === 'loading') { - template = 'centeredContent'; - } - - return ( - - - {kubeBeatQuery.status === 'loading' && {LOADING}} - {kubeBeatQuery.status === 'error' && ( - -

- -

- - } - /> - )} - {kubeBeatQuery.status === 'success' && children} -
-
- ); -}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/translations.ts b/x-pack/plugins/cloud_security_posture/public/components/translations.ts index b203d0365a28f..facbbcc3176da 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/translations.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/translations.ts @@ -40,28 +40,27 @@ export const CSP_EVALUATION_BADGE_PASSED = i18n.translate( } ); -export const NO_DATA_CONFIG_TITLE = i18n.translate('xpack.csp.pageTemplate.noDataConfigTitle', { - defaultMessage: 'Understand your cloud security posture', -}); - -export const NO_DATA_CONFIG_SOLUTION_NAME = i18n.translate( - 'xpack.csp.pageTemplate.noDataConfig.solutionNameLabel', - { +export const PACKAGE_NOT_INSTALLED_TEXT = { + PAGE_TITLE: i18n.translate('xpack.csp.cspPageTemplate.packageNotInstalled.pageTitle', { + defaultMessage: 'Install Integration to get started', + }), + SOLUTION: i18n.translate('xpack.csp.cspPageTemplate.packageNotInstalled.solutionNameLabel', { defaultMessage: 'Cloud Security Posture', - } -); - -export const NO_DATA_CONFIG_DESCRIPTION = i18n.translate( - 'xpack.csp.pageTemplate.noDataConfigDescription', - { + }), + BUTTON_TITLE: i18n.translate('xpack.csp.cspPageTemplate.packageNotInstalled.buttonLabel', { + defaultMessage: 'Add a CIS integration', + }), + DESCRIPTION: i18n.translate('xpack.csp.cspPageTemplate.packageNotInstalled.description', { defaultMessage: 'Use our CIS Kubernetes Benchmark integration to measure your Kubernetes cluster setup against the CIS recommendations.', - } -); + }), +}; -export const NO_DATA_CONFIG_BUTTON = i18n.translate( - 'xpack.csp.pageTemplate.noDataConfigButtonLabel', - { - defaultMessage: 'Add a CIS integration', - } -); +export const DEFAULT_NO_DATA_TEXT = { + PAGE_TITLE: i18n.translate('xpack.csp.cspPageTemplate.defaultNoDataConfig.pageTitle', { + defaultMessage: 'No data found', + }), + SOLUTION: i18n.translate('xpack.csp.cspPageTemplate.defaultNoDataConfig.solutionNameLabel', { + defaultMessage: 'Cloud Security Posture', + }), +}; diff --git a/x-pack/plugins/cloud_security_posture/public/components/unknown_route.tsx b/x-pack/plugins/cloud_security_posture/public/components/unknown_route.tsx index 248d598302b9f..90a469ba2dd48 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/unknown_route.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/unknown_route.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { EuiEmptyPrompt } from '@elastic/eui'; -import { CspPageTemplate } from './page_template'; +import { CspPageTemplate } from './csp_page_template'; import * as TEXT from './translations'; export const UnknownRoute = React.memo(() => ( diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx index 983c58f2d5d7c..918294794e9d2 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.test.tsx @@ -21,13 +21,20 @@ import { TABLE_COLUMN_HEADERS, } from './translations'; import { useCspBenchmarkIntegrations } from './use_csp_benchmark_integrations'; +import { useCisKubernetesIntegration } from '../../common/api/use_cis_kubernetes_integration'; jest.mock('./use_csp_benchmark_integrations'); jest.mock('../../common/api/use_kubebeat_data_view'); +jest.mock('../../common/api/use_cis_kubernetes_integration'); describe('', () => { beforeEach(() => { jest.resetAllMocks(); + + // if package installation status is 'not_installed', CspPageTemplate will render a noDataConfig prompt + (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ + data: { item: { status: 'installed' } }, + })); // Required for the page template to render the benchmarks page (useKubebeatDataView as jest.Mock).mockImplementation(() => createReactQueryResponse({ diff --git a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx index e7f8991eedf8f..e303c619a8d01 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/benchmarks/benchmarks.tsx @@ -4,6 +4,8 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + +import React, { useState } from 'react'; import { EuiFieldSearch, EuiFieldSearchProps, @@ -15,13 +17,12 @@ import { EuiTextColor, EuiText, } from '@elastic/eui'; -import React, { useState } from 'react'; import { FormattedMessage } from '@kbn/i18n-react'; import useDebounce from 'react-use/lib/useDebounce'; import { allNavigationItems } from '../../common/navigation/constants'; import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs'; import { useCISIntegrationLink } from '../../common/navigation/use_navigate_to_cis_integration'; -import { CspPageTemplate } from '../../components/page_template'; +import { CspPageTemplate } from '../../components/csp_page_template'; import { BenchmarksTable } from './benchmarks_table'; import { ADD_A_CIS_INTEGRATION, BENCHMARK_INTEGRATIONS } from './translations'; import { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx index 1e355b3f3c82f..086fea34a2c50 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_charts/risks_table.tsx @@ -14,7 +14,7 @@ import { EuiLink, EuiText, } from '@elastic/eui'; -import { CloudPostureStats, ResourceType } from '../../../../common/types'; +import { ComplianceDashboardData, ResourceType } from '../../../../common/types'; import { CompactFormattedNumber } from '../../../components/compact_formatted_number'; import * as TEXT from '../translations'; import { INTERNAL_FEATURE_FLAGS } from '../../../../common/constants'; @@ -59,14 +59,14 @@ const mockData = [ ]; export interface RisksTableProps { - data: CloudPostureStats['resourcesTypes']; + data: ComplianceDashboardData['resourcesTypes']; maxItems: number; onCellClick: (resourceTypeName: string) => void; onViewAllClick: () => void; } export const getTopRisks = ( - resourcesTypes: CloudPostureStats['resourcesTypes'], + resourcesTypes: ComplianceDashboardData['resourcesTypes'], maxItems: number ) => { const filtered = resourcesTypes.filter((x) => x.totalFailed > 0); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx index 07b5294a8d4ae..ff564744384e0 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/compliance_dashboard.tsx @@ -6,40 +6,51 @@ */ import React from 'react'; -import { EuiSpacer } from '@elastic/eui'; +import { EuiSpacer, EuiIcon } from '@elastic/eui'; import { allNavigationItems } from '../../common/navigation/constants'; import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs'; import { SummarySection } from './dashboard_sections/summary_section'; import { BenchmarksSection } from './dashboard_sections/benchmarks_section'; -import { useCloudPostureStatsApi } from '../../common/api'; -import { CspPageTemplate } from '../../components/page_template'; -import * as TEXT from './translations'; +import { useComplianceDashboardDataApi } from '../../common/api'; +import { CspPageTemplate } from '../../components/csp_page_template'; +import { type KibanaPageTemplateProps } from '../../../../../../src/plugins/kibana_react/public'; +import { CLOUD_POSTURE, NO_DATA_CONFIG_TEXT } from './translations'; -const CompliancePage = () => { - const getStats = useCloudPostureStatsApi(); - if (getStats.isLoading) return null; - - return ( - <> - - - - - - ); -}; +const getNoDataConfig = (onClick: () => void): KibanaPageTemplateProps['noDataConfig'] => ({ + pageTitle: NO_DATA_CONFIG_TEXT.PAGE_TITLE, + solution: NO_DATA_CONFIG_TEXT.SOLUTION, + // TODO: Add real docs link once we have it + docsLink: 'https://www.elastic.co/guide/index.html', + logo: 'logoSecurity', + actions: { + dashboardNoDataCard: { + icon: , + onClick, + title: NO_DATA_CONFIG_TEXT.BUTTON_TITLE, + description: NO_DATA_CONFIG_TEXT.DESCRIPTION, + }, + }, +}); export const ComplianceDashboard = () => { + const getDashboardDataQuery = useComplianceDashboardDataApi(); useCspBreadcrumbs([allNavigationItems.dashboard]); return ( - + {getDashboardDataQuery.data && ( + <> + + + + + + )} ); }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx index 0fc8f0d3d0bef..565811bca7ee7 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/dashboard_sections/benchmarks_section.tsx @@ -17,34 +17,25 @@ import { useEuiTheme, } from '@elastic/eui'; import moment from 'moment'; -import { EuiIconType } from '@elastic/eui/src/components/icon/icon'; import { PartitionElementEvent } from '@elastic/charts'; import { EuiThemeComputed } from '@elastic/eui/src/services/theme/types'; import { CloudPostureScoreChart } from '../compliance_charts/cloud_posture_score_chart'; -import { useCloudPostureStatsApi } from '../../../common/api/use_cloud_posture_stats_api'; import { ChartPanel } from '../../../components/chart_panel'; import * as TEXT from '../translations'; -import { Evaluation } from '../../../../common/types'; +import type { ComplianceDashboardData, Evaluation } from '../../../../common/types'; import { RisksTable } from '../compliance_charts/risks_table'; import { INTERNAL_FEATURE_FLAGS, RULE_FAILED } from '../../../../common/constants'; import { useNavigateFindings } from '../../../common/hooks/use_navigate_findings'; -const logoMap: ReadonlyMap = new Map([['CIS Kubernetes', 'logoKubernetes']]); - -const getBenchmarkLogo = (benchmarkName: string): EuiIconType => { - return logoMap.get(benchmarkName) ?? 'logoElastic'; -}; - -const mockClusterId = '2468540'; - const cardHeight = 300; -export const BenchmarksSection = () => { +export const BenchmarksSection = ({ + complianceData, +}: { + complianceData: ComplianceDashboardData; +}) => { const { euiTheme } = useEuiTheme(); const navToFindings = useNavigateFindings(); - const getStats = useCloudPostureStatsApi(); - const clusters = getStats.isSuccess && getStats.data.clusters; - if (!clusters) return null; const handleElementClick = (clusterId: string, elements: PartitionElementEvent[]) => { const [element] = elements; @@ -68,7 +59,7 @@ export const BenchmarksSection = () => { return ( <> - {clusters.map((cluster) => { + {complianceData.clusters.map((cluster) => { const shortId = cluster.meta.clusterId.slice(0, 6); return ( @@ -82,7 +73,7 @@ export const BenchmarksSection = () => {

{cluster.meta.benchmarkName}

-

{`Cluster ID ${shortId || mockClusterId}`}

+

{`Cluster ID ${shortId}`}

@@ -91,7 +82,8 @@ export const BenchmarksSection = () => { - + {/* TODO: change default k8s logo to use a getBenchmarkLogo function */} + {INTERNAL_FEATURE_FLAGS.showManageRulesMock && ( @@ -104,12 +96,7 @@ export const BenchmarksSection = () => { grow={4} style={{ borderRight: `1px solid ${euiTheme.colors.lightShade}` }} > - + { - + { +export const SummarySection = ({ complianceData }: { complianceData: ComplianceDashboardData }) => { const navToFindings = useNavigateFindings(); - const getStats = useCloudPostureStatsApi(); - if (!getStats.isSuccess) return null; const handleElementClick = (elements: PartitionElementEvent[]) => { const [element] = elements; @@ -49,22 +46,18 @@ export const SummarySection = () => { return ( - + - + { - + diff --git a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/translations.ts b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/translations.ts index 87193ef67fa3a..0e87681037c66 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/translations.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/compliance_dashboard/translations.ts @@ -82,3 +82,18 @@ export const RESOURCE_TYPE = i18n.translate('xpack.csp.resource_type', { export const FINDINGS = i18n.translate('xpack.csp.findings', { defaultMessage: 'Findings', }); + +export const NO_DATA_CONFIG_TEXT = { + PAGE_TITLE: i18n.translate('xpack.csp.complianceDashboard.noDataConfig.pageTitle', { + defaultMessage: 'Cloud Security Compliance Dashboard', + }), + SOLUTION: i18n.translate('xpack.csp.complianceDashboard.noDataConfig.solutionNameLabel', { + defaultMessage: 'Cloud Security Posture', + }), + BUTTON_TITLE: i18n.translate('xpack.csp.complianceDashboard.noDataConfig.actionTitle', { + defaultMessage: 'Try Again', + }), + DESCRIPTION: i18n.translate('xpack.csp.complianceDashboard.noDataConfig.actionDescription', { + defaultMessage: 'You can try to refetch your data', + }), +}; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx index 54f1ecf9f31ed..1094d5fa847de 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.test.tsx @@ -17,9 +17,11 @@ import { import { createStubDataView } from '../../../../../../src/plugins/data_views/public/data_views/data_view.stub'; import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../../common/constants'; import * as TEST_SUBJECTS from './test_subjects'; +import { useCisKubernetesIntegration } from '../../common/api/use_cis_kubernetes_integration'; import type { DataView } from '../../../../../../src/plugins/data/common'; jest.mock('../../common/api/use_kubebeat_data_view'); +jest.mock('../../common/api/use_cis_kubernetes_integration'); beforeEach(() => { jest.restoreAllMocks(); @@ -36,6 +38,9 @@ describe('', () => { const data = dataPluginMock.createStartContract(); const source = await data.search.searchSource.create(); + (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ + data: { item: { status: 'installed' } }, + })); (source.fetch$ as jest.Mock).mockReturnValue({ toPromise: () => Promise.resolve({ rawResponse: { hits: { hits: [] } } }), }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx index 6ed043361b44f..fba8fc37f54d1 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/findings/findings.tsx @@ -10,7 +10,7 @@ import { useKubebeatDataView } from '../../common/api/use_kubebeat_data_view'; import { allNavigationItems } from '../../common/navigation/constants'; import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs'; import { FindingsContainer } from './findings_container'; -import { CspPageTemplate } from '../../components/page_template'; +import { CspPageTemplate } from '../../components/csp_page_template'; import { FINDINGS } from './translations'; const pageHeader: EuiPageHeaderProps = { @@ -18,15 +18,12 @@ const pageHeader: EuiPageHeaderProps = { }; export const Findings = () => { - const dataView = useKubebeatDataView(); + const dataViewQuery = useKubebeatDataView(); useCspBreadcrumbs([allNavigationItems.findings]); return ( - // `CspPageTemplate` takes care of loading and error states for the kubebeat data view, no need to handle them here - - {dataView.status === 'success' && dataView.data && ( - - )} + + {dataViewQuery.data && } ); }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx index bcfc06e8e16a5..288f9e2f30c01 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/index.tsx @@ -4,19 +4,19 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import React, { useMemo } from 'react'; import { RouteComponentProps } from 'react-router-dom'; import { EuiTextColor, EuiEmptyPrompt } from '@elastic/eui'; import * as t from 'io-ts'; -import { CspPageTemplate } from '../../components/page_template'; import { RulesContainer, type PageUrlParams } from './rules_container'; import { allNavigationItems } from '../../common/navigation/constants'; import { useCspBreadcrumbs } from '../../common/navigation/use_csp_breadcrumbs'; import type { KibanaPageTemplateProps } from '../../../../../../src/plugins/kibana_react/public'; -import { CspLoadingState } from '../../components/csp_loading_state'; import { CspNavigationItem } from '../../common/navigation/types'; import { extractErrorMessage } from '../../../common/utils/helpers'; import { useCspIntegration } from './use_csp_integration'; +import { CspPageTemplate } from '../../components/csp_page_template'; const getRulesBreadcrumbs = (name?: string): CspNavigationItem[] => [allNavigationItems.benchmarks, { ...allNavigationItems.rules, name }].filter( @@ -35,7 +35,6 @@ export const Rules = ({ match: { params } }: RouteComponentProps) const pageProps: KibanaPageTemplateProps = useMemo( () => ({ - template: integrationInfo.status !== 'success' ? 'centeredContent' : undefined, pageHeader: { bottomBorder: false, // TODO: border still shows. pageTitle: 'Rules', @@ -46,16 +45,16 @@ export const Rules = ({ match: { params } }: RouteComponentProps) ), }, }), - [integrationInfo.data, integrationInfo.status] + [integrationInfo.data] ); return ( - + } + > {integrationInfo.status === 'success' && } - {integrationInfo.status === 'error' && ( - - )} - {integrationInfo.status === 'loading' && } ); }; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx index aaf7bdc557e21..bf5badfca1d95 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules.test.tsx @@ -15,10 +15,12 @@ import { type RouteComponentProps } from 'react-router-dom'; import { cspLoadingStateTestId } from '../../components/csp_loading_state'; import type { PageUrlParams } from './rules_container'; import * as TEST_SUBJECTS from './test_subjects'; +import { useCisKubernetesIntegration } from '../../common/api/use_cis_kubernetes_integration'; jest.mock('./use_csp_integration', () => ({ useCspIntegration: jest.fn(), })); +jest.mock('../../common/api/use_cis_kubernetes_integration'); const queryClient = new QueryClient({ defaultOptions: { @@ -43,6 +45,9 @@ describe('', () => { beforeEach(() => { queryClient.clear(); jest.clearAllMocks(); + (useCisKubernetesIntegration as jest.Mock).mockImplementation(() => ({ + data: { item: { status: 'installed' } }, + })); }); it('calls API with URL params', async () => { @@ -63,6 +68,7 @@ describe('', () => { const Component = getTestComponent({ packagePolicyId: '1', policyId: '2' }); const request = { status: 'error', + isError: true, data: null, error: new Error('some error message'), }; @@ -78,6 +84,7 @@ describe('', () => { const Component = getTestComponent({ packagePolicyId: '21', policyId: '22' }); const request = { status: 'loading', + isLoading: true, }; (useCspIntegration as jest.Mock).mockReturnValue(request); diff --git a/x-pack/plugins/cloud_security_posture/public/test/fixtures/react_query.ts b/x-pack/plugins/cloud_security_posture/public/test/fixtures/react_query.ts index 2e6eeb5addb0a..201a8d85b4278 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/fixtures/react_query.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/fixtures/react_query.ts @@ -22,11 +22,15 @@ export const createReactQueryResponse = ({ data = undefined, }: CreateReactQueryResponseInput = {}): Partial> => { if (status === 'success') { - return { status, data }; + return { status, data, isSuccess: true, isLoading: false, isError: false }; } if (status === 'error') { - return { status, error }; + return { status, error, isSuccess: false, isLoading: false, isError: true }; + } + + if (status === 'loading') { + return { status, data: undefined, isSuccess: false, isLoading: true, isError: false }; } return { status }; diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts index e414dab92606a..154c2d58cd330 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/compliance_dashboard.ts @@ -13,7 +13,7 @@ import type { QueryDslQueryContainer, SearchRequest, } from '@elastic/elasticsearch/lib/api/types'; -import type { CloudPostureStats } from '../../../common/types'; +import type { ComplianceDashboardData } from '../../../common/types'; import { CSP_KUBEBEAT_INDEX_PATTERN, STATS_ROUTE_PATH } from '../../../common/constants'; import { CspAppContext } from '../../plugin'; import { getResourcesTypes } from './get_resources_types'; @@ -102,7 +102,7 @@ export const defineGetComplianceDashboardRoute = ( getClusters(esClient, query), ]); - const body: CloudPostureStats = { + const body: ComplianceDashboardData = { stats, resourcesTypes, clusters, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.test.ts index df45e7fb8e737..1630d4fe3537f 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.test.ts @@ -51,7 +51,7 @@ const mockClusterBuckets: ClusterBucket[] = [ ]; describe('getClustersFromAggs', () => { - it('should return value matching CloudPostureStats["clusters"]', async () => { + it('should return value matching ComplianceDashboardData["clusters"]', async () => { const clusters = getClustersFromAggs(mockClusterBuckets); expect(clusters).toEqual([ { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts index 04eecd67cc283..98171bf5ec332 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_clusters.ts @@ -11,7 +11,7 @@ import type { QueryDslQueryContainer, SearchRequest, } from '@elastic/elasticsearch/lib/api/types'; -import { CloudPostureStats } from '../../../common/types'; +import { ComplianceDashboardData } from '../../../common/types'; import { getResourceTypeFromAggs, resourceTypeAggQuery } from './get_resources_types'; import type { ResourceTypeQueryResult } from './get_resources_types'; import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../../common/constants'; @@ -66,7 +66,9 @@ export const getClustersQuery = (query: QueryDslQueryContainer): SearchRequest = }, }); -export const getClustersFromAggs = (clusters: ClusterBucket[]): CloudPostureStats['clusters'] => +export const getClustersFromAggs = ( + clusters: ClusterBucket[] +): ComplianceDashboardData['clusters'] => clusters.map((cluster) => { // get cluster's meta data const benchmarks = cluster.benchmarks.buckets; @@ -101,7 +103,7 @@ export const getClustersFromAggs = (clusters: ClusterBucket[]): CloudPostureStat export const getClusters = async ( esClient: ElasticsearchClient, query: QueryDslQueryContainer -): Promise => { +): Promise => { const queryResult = await esClient.search(getClustersQuery(query), { meta: true, }); diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_resources_types.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_resources_types.test.ts index b01644fc3f45b..411290738f33e 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_resources_types.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_resources_types.test.ts @@ -31,7 +31,7 @@ const resourceTypeBuckets: ResourceTypeBucket[] = [ ]; describe('getResourceTypeFromAggs', () => { - it('should return value matching CloudPostureStats["resourcesTypes"]', async () => { + it('should return value matching ComplianceDashboardData["resourcesTypes"]', async () => { const resourceTypes = getResourceTypeFromAggs(resourceTypeBuckets); expect(resourceTypes).toEqual([ { diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_resources_types.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_resources_types.ts index 0fc6e4b00944a..8d31fb7a8e88d 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_resources_types.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_resources_types.ts @@ -6,12 +6,12 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { +import type { AggregationsMultiBucketAggregateBase as Aggregation, QueryDslQueryContainer, SearchRequest, } from '@elastic/elasticsearch/lib/api/types'; -import { CloudPostureStats } from '../../../common/types'; +import type { ComplianceDashboardData } from '../../../common/types'; import { KeyDocCount } from './compliance_dashboard'; import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../../common/constants'; @@ -53,7 +53,7 @@ export const getRisksEsQuery = (query: QueryDslQueryContainer): SearchRequest => export const getResourceTypeFromAggs = ( queryResult: ResourceTypeBucket[] -): CloudPostureStats['resourcesTypes'] => +): ComplianceDashboardData['resourcesTypes'] => queryResult.map((bucket) => ({ name: bucket.key, totalFindings: bucket.doc_count, @@ -64,7 +64,7 @@ export const getResourceTypeFromAggs = ( export const getResourcesTypes = async ( esClient: ElasticsearchClient, query: QueryDslQueryContainer -): Promise => { +): Promise => { const resourceTypesQueryResult = await esClient.search( getRisksEsQuery(query), { meta: true } diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.test.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.test.ts index 558fec85860ea..27404533afeb0 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.test.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.test.ts @@ -59,7 +59,7 @@ describe('getStatsFromFindingsEvaluationsAggs', () => { expect(score).toEqual(36.4); }); - it('should return value matching CloudPostureStats["stats"]', async () => { + it('should return value matching ComplianceDashboardData["stats"]', async () => { const stats = getStatsFromFindingsEvaluationsAggs(standardQueryResult); expect(stats).toEqual({ totalFailed: 30, diff --git a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts index 8d5417de24c52..82d1dd9a5d49f 100644 --- a/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts +++ b/x-pack/plugins/cloud_security_posture/server/routes/compliance_dashboard/get_stats.ts @@ -6,9 +6,9 @@ */ import { ElasticsearchClient } from 'kibana/server'; -import { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; +import type { QueryDslQueryContainer, SearchRequest } from '@elastic/elasticsearch/lib/api/types'; import { CSP_KUBEBEAT_INDEX_PATTERN } from '../../../common/constants'; -import { CloudPostureStats, Score } from '../../../common/types'; +import type { ComplianceDashboardData, Score } from '../../../common/types'; /** * @param value value is [0, 1] range @@ -44,7 +44,7 @@ export const getEvaluationsQuery = (query: QueryDslQueryContainer): SearchReques export const getStatsFromFindingsEvaluationsAggs = ( findingsEvaluationsAggs: FindingsEvaluationsQueryResult -): CloudPostureStats['stats'] => { +): ComplianceDashboardData['stats'] => { const failedFindings = findingsEvaluationsAggs.failed_findings.doc_count || 0; const passedFindings = findingsEvaluationsAggs.passed_findings.doc_count || 0; const totalFindings = failedFindings + passedFindings; @@ -62,7 +62,7 @@ export const getStatsFromFindingsEvaluationsAggs = ( export const getStats = async ( esClient: ElasticsearchClient, query: QueryDslQueryContainer -): Promise => { +): Promise => { const evaluationsQueryResult = await esClient.search( getEvaluationsQuery(query), { meta: true } From 43ad6e2597dfebe5055189c31a442f1ca11d7dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Tue, 29 Mar 2022 11:42:32 +0200 Subject: [PATCH 10/31] [Security solution] [Endpoint] Updates translations in policy details tab for blocklist and trusted applications (#128466) * Updates translations in policy details tab for blocklist and trusted apps * Fix wrong search placeholder on blocklist list page * Fix wrong blocklist translation key * Fixes more multilangs * Adds 'entry' word next to 'blocklist' for singular reference Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../pages/blocklist/view/blocklist.tsx | 3 ++ .../view/tabs/blocklists_translations.ts | 47 ++++++++++--------- .../pages/policy/view/tabs/policy_tabs.tsx | 6 +-- .../view/tabs/trusted_apps_translations.ts | 44 ++++++++--------- 4 files changed, 52 insertions(+), 48 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/blocklist/view/blocklist.tsx b/x-pack/plugins/security_solution/public/management/pages/blocklist/view/blocklist.tsx index 75d4b22fe16a1..c4d4edb5e1331 100644 --- a/x-pack/plugins/security_solution/public/management/pages/blocklist/view/blocklist.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/blocklist/view/blocklist.tsx @@ -95,6 +95,9 @@ const BLOCKLIST_PAGE_LABELS: ArtifactListPageProps['labels'] = { 'xpack.securitySolution.blocklist.emptyStatePrimaryButtonLabel', { defaultMessage: 'Add blocklist' } ), + searchPlaceholderInfo: i18n.translate('xpack.securitySolution.blocklist.searchPlaceholderInfo', { + defaultMessage: 'Search on the fields below: name, description, value', + }), }; export const Blocklist = memo(() => { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/blocklists_translations.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/blocklists_translations.ts index 9eb2d57a506b3..0bc32d35ea341 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/blocklists_translations.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/blocklists_translations.ts @@ -12,20 +12,20 @@ export const POLICY_ARTIFACT_BLOCKLISTS_LABELS = Object.freeze({ deleteModalTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.list.removeDialog.title', { - defaultMessage: 'Remove blocklist from policy', + defaultMessage: 'Remove blocklist entry from policy', } ), deleteModalImpactInfo: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.list.removeDialog.messageCallout', { defaultMessage: - 'This blocklist will be removed only from this policy and can still be found and managed from the artifact page.', + 'This blocklist entry will be removed only from this policy and can still be found and managed from the artifact page.', } ), deleteModalErrorMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.list.removeDialog.errorToastTitle', { - defaultMessage: 'Error while attempting to remove blocklist', + defaultMessage: 'Error while attempting to remove blocklist entry', } ), flyoutWarningCalloutMessage: (maxNumber: number) => @@ -33,37 +33,37 @@ export const POLICY_ARTIFACT_BLOCKLISTS_LABELS = Object.freeze({ 'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.searchWarning.text', { defaultMessage: - 'Only the first {maxNumber} blocklists are displayed. Please use the search bar to refine the results.', + 'Only the first {maxNumber} blocklist entries are displayed. Please use the search bar to refine the results.', values: { maxNumber }, } ), flyoutNoArtifactsToBeAssignedMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.noAssignable', { - defaultMessage: 'There are no blocklists that can be assigned to this policy.', + defaultMessage: 'There are no blocklist entries that can be assigned to this policy.', } ), flyoutTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.title', { - defaultMessage: 'Assign blocklists', + defaultMessage: 'Assign blocklist entries', } ), flyoutSubtitle: (policyName: string): string => i18n.translate('xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.subtitle', { - defaultMessage: 'Select blocklists to add to {policyName}', + defaultMessage: 'Select blocklist entries to add to {policyName}', values: { policyName }, }), flyoutSearchPlaceholder: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.layout.search.label', { - defaultMessage: 'Search blocklists', + defaultMessage: 'Search blocklist entries', } ), flyoutErrorMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.toastError.text', { - defaultMessage: `An error occurred updating blocklists`, + defaultMessage: `An error occurred updating blocklist entry`, } ), flyoutSuccessMessageText: (updatedExceptions: ExceptionListItemSchema[]): string => @@ -71,56 +71,57 @@ export const POLICY_ARTIFACT_BLOCKLISTS_LABELS = Object.freeze({ ? i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.toastSuccess.textMultiples', { - defaultMessage: '{count} blocklists have been added to your list.', + defaultMessage: '{count} blocklist entries have been added to your list.', values: { count: updatedExceptions.length }, } ) : i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.layout.flyout.toastSuccess.textSingle', { - defaultMessage: '"{name}" has been added to your blocklist list.', + defaultMessage: '"{name}" blocklist has been added to your list.', values: { name: updatedExceptions[0].name }, } ), emptyUnassignedTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.empty.unassigned.title', - { defaultMessage: 'No assigned blocklists' } + { defaultMessage: 'No assigned blocklist entries' } ), emptyUnassignedMessage: (policyName: string): string => i18n.translate('xpack.securitySolution.endpoint.policy.blocklists.empty.unassigned.content', { defaultMessage: - 'There are currently no blocklists assigned to {policyName}. Assign blocklists now or add and manage them on the blocklists page.', + 'There are currently no blocklist entries assigned to {policyName}. Assign blocklist entries now or add and manage them on the blocklist page.', values: { policyName }, }), emptyUnassignedPrimaryActionButtonTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.empty.unassigned.primaryAction', { - defaultMessage: 'Assign blocklists', + defaultMessage: 'Assign blocklist entry', } ), emptyUnassignedSecondaryActionButtonTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.empty.unassigned.secondaryAction', { - defaultMessage: 'Manage blocklists', + defaultMessage: 'Manage blocklist entries', } ), emptyUnexistingTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.empty.unexisting.title', - { defaultMessage: 'No blocklists exist' } + { defaultMessage: 'No blocklist entries exist' } ), emptyUnexistingMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.empty.unexisting.content', { - defaultMessage: 'There are currently no blocklists applied to your endpoints.', + defaultMessage: 'There are currently no blocklist entries applied to your endpoints.', } ), emptyUnexistingPrimaryActionButtonTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.empty.unexisting.action', - { defaultMessage: 'Add blocklists' } + { defaultMessage: 'Add blocklist entry' } ), listTotalItemCountMessage: (totalItemsCount: number): string => i18n.translate('xpack.securitySolution.endpoint.policy.blocklists.list.totalItemCount', { - defaultMessage: 'Showing {totalItemsCount, plural, one {# blocklist} other {# blocklists}}', + defaultMessage: + 'Showing {totalItemsCount, plural, one {# blocklist entry} other {# blocklist entries}}', values: { totalItemsCount }, }), listRemoveActionNotAllowedMessage: i18n.translate( @@ -132,22 +133,22 @@ export const POLICY_ARTIFACT_BLOCKLISTS_LABELS = Object.freeze({ listSearchPlaceholderMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.list.search.placeholder', { - defaultMessage: `Search on the fields below: name, description, IP`, + defaultMessage: `Search on the fields below: name, description, value`, } ), layoutTitle: i18n.translate('xpack.securitySolution.endpoint.policy.blocklists.layout.title', { - defaultMessage: 'Assigned blocklists', + defaultMessage: 'Assigned blocklist entries', }), layoutAssignButtonTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.layout.assignToPolicy', { - defaultMessage: 'Assign blocklists to policy', + defaultMessage: 'Assign blocklist entry to policy', } ), layoutViewAllLinkMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.blocklists.layout.about.viewAllLinkLabel', { - defaultMessage: 'view all blocklists', + defaultMessage: 'view all blocklist entries', } ), }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx index 17c880ffa6261..6b40477c7bb6f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/policy_tabs.tsx @@ -123,7 +123,7 @@ export const PolicyTabs = React.memo(() => { layoutAboutMessage: (count: number, link: React.ReactElement): React.ReactNode => ( ), @@ -156,7 +156,7 @@ export const PolicyTabs = React.memo(() => { layoutAboutMessage: (count: number, link: React.ReactElement): React.ReactNode => ( ), @@ -241,7 +241,7 @@ export const PolicyTabs = React.memo(() => { [PolicyTabKeys.BLOCKLISTS]: { id: PolicyTabKeys.BLOCKLISTS, name: i18n.translate('xpack.securitySolution.endpoint.policy.details.tabs.blocklists', { - defaultMessage: 'Blocklists', + defaultMessage: 'Blocklist', }), content: ( <> diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/trusted_apps_translations.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/trusted_apps_translations.ts index f83568498df25..b990c2f9fc26c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/trusted_apps_translations.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/tabs/trusted_apps_translations.ts @@ -12,14 +12,14 @@ export const POLICY_ARTIFACT_TRUSTED_APPS_LABELS = Object.freeze({ deleteModalTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.list.removeDialog.title', { - defaultMessage: 'Remove trusted app from policy', + defaultMessage: 'Remove trusted application from policy', } ), deleteModalImpactInfo: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.list.removeDialog.messageCallout', { defaultMessage: - 'This trusted app will be removed only from this policy and can still be found and managed from the artifact page.', + 'This trusted application will be removed only from this policy and can still be found and managed from the artifact page.', } ), deleteModalErrorMessage: i18n.translate( @@ -33,37 +33,37 @@ export const POLICY_ARTIFACT_TRUSTED_APPS_LABELS = Object.freeze({ 'xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.searchWarning.text', { defaultMessage: - 'Only the first {maxNumber} trusted apps are displayed. Please use the search bar to refine the results.', + 'Only the first {maxNumber} trusted applications are displayed. Please use the search bar to refine the results.', values: { maxNumber }, } ), flyoutNoArtifactsToBeAssignedMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.noAssignable', { - defaultMessage: 'There are no trusted apps that can be assigned to this policy.', + defaultMessage: 'There are no trusted applications that can be assigned to this policy.', } ), flyoutTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.title', { - defaultMessage: 'Assign trusted apps', + defaultMessage: 'Assign trusted applications', } ), flyoutSubtitle: (policyName: string): string => i18n.translate('xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.subtitle', { - defaultMessage: 'Select trusted apps to add to {policyName}', + defaultMessage: 'Select trusted applications to add to {policyName}', values: { policyName }, }), flyoutSearchPlaceholder: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.layout.search.label', { - defaultMessage: 'Search trusted apps', + defaultMessage: 'Search trusted applications', } ), flyoutErrorMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.toastError.text', { - defaultMessage: `An error occurred updating trusted apps`, + defaultMessage: `An error occurred updating trusted applications`, } ), flyoutSuccessMessageText: (updatedExceptions: ExceptionListItemSchema[]): string => @@ -71,61 +71,61 @@ export const POLICY_ARTIFACT_TRUSTED_APPS_LABELS = Object.freeze({ ? i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.toastSuccess.textMultiples', { - defaultMessage: '{count} trusted apps have been added to your list.', + defaultMessage: '{count} trusted applications have been added to your list.', values: { count: updatedExceptions.length }, } ) : i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.toastSuccess.textSingle', { - defaultMessage: '"{name}" has been added to your trusted app list.', + defaultMessage: '"{name}" has been added to your trusted application list.', values: { name: updatedExceptions[0].name }, } ), emptyUnassignedTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.empty.unassigned.title', - { defaultMessage: 'No assigned trusted apps' } + { defaultMessage: 'No assigned trusted applications' } ), emptyUnassignedMessage: (policyName: string): string => i18n.translate('xpack.securitySolution.endpoint.policy.trustedApps.empty.unassigned.content', { defaultMessage: - 'There are currently no trusted apps assigned to {policyName}. Assign trusted apps now or add and manage them on the trusted apps page.', + 'There are currently no trusted applications assigned to {policyName}. Assign trusted applications now or add and manage them on the trusted applications page.', values: { policyName }, }), emptyUnassignedPrimaryActionButtonTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.empty.unassigned.primaryAction', { - defaultMessage: 'Assign trusted apps', + defaultMessage: 'Assign trusted applications', } ), emptyUnassignedSecondaryActionButtonTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.empty.unassigned.secondaryAction', { - defaultMessage: 'Manage trusted apps', + defaultMessage: 'Manage trusted applications', } ), emptyUnexistingTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.empty.unexisting.title', - { defaultMessage: 'No trusted apps exist' } + { defaultMessage: 'No trusted applications exist' } ), emptyUnexistingMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.empty.unexisting.content', - { defaultMessage: 'There are currently no trusted apps applied to your endpoints.' } + { defaultMessage: 'There are currently no trusted applications applied to your endpoints.' } ), emptyUnexistingPrimaryActionButtonTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.empty.unexisting.action', - { defaultMessage: 'Add trusted apps' } + { defaultMessage: 'Add trusted applications' } ), listTotalItemCountMessage: (totalItemsCount: number): string => i18n.translate('xpack.securitySolution.endpoint.policy.trustedApps.list.totalItemCount', { defaultMessage: - 'Showing {totalItemsCount, plural, one {# trusted app} other {# trusted apps}}', + 'Showing {totalItemsCount, plural, one {# trusted app} other {# trusted applications}}', values: { totalItemsCount }, }), listRemoveActionNotAllowedMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.list.removeActionNotAllowed', { - defaultMessage: 'Globally applied trusted app cannot be removed from policy.', + defaultMessage: 'Globally applied trusted application cannot be removed from policy.', } ), listSearchPlaceholderMessage: i18n.translate( @@ -135,18 +135,18 @@ export const POLICY_ARTIFACT_TRUSTED_APPS_LABELS = Object.freeze({ } ), layoutTitle: i18n.translate('xpack.securitySolution.endpoint.policy.trustedApps.layout.title', { - defaultMessage: 'Assigned trusted apps', + defaultMessage: 'Assigned trusted applications', }), layoutAssignButtonTitle: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.layout.assignToPolicy', { - defaultMessage: 'Assign trusted apps to policy', + defaultMessage: 'Assign trusted applications to policy', } ), layoutViewAllLinkMessage: i18n.translate( 'xpack.securitySolution.endpoint.policy.trustedApps.layout.about.viewAllLinkLabel', { - defaultMessage: 'view all trusted apps', + defaultMessage: 'view all trusted applications', } ), }); From bf2769d7ee5994c73532739d47ca896a319740b9 Mon Sep 17 00:00:00 2001 From: Sander Philipse <94373878+sphilipse@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:31:05 +0200 Subject: [PATCH 11/31] [Workplace Search] Add source skips config step correctly (#128715) --- .../components/add_source/add_source.test.tsx | 5 ++++- .../content_sources/components/add_source/add_source.tsx | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx index e9cbafd01003e..48e57d92272ba 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.test.tsx @@ -81,7 +81,10 @@ describe('AddSourceList', () => { configured: true, }; shallow(); - expect(initializeAddSource).toHaveBeenCalledWith(expect.objectContaining({ connect: true })); + expect(initializeAddSource).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ connect: true }) + ); }); it('renders default state correctly when there are multiple connector options', () => { diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.tsx index 3fa316333bccc..98e9f32bb33ac 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/add_source/add_source.tsx @@ -59,9 +59,9 @@ export const AddSource: React.FC = (props) => { // We can land on this page from a choice page for multiple types of connectors // If that's the case we want to skip the intro and configuration, if the external & internal connector have already been configured const goToConnect = externalConnectorAvailable && externalConfigured && configured; - initializeAddSource(goToConnect ? props : { ...props, connect: true }); + initializeAddSource(goToConnect ? { ...props, connect: true } : props); return resetSourceState; - }, []); + }, [configured]); const goToConfigurationIntro = () => setAddSourceStep(AddSourceSteps.ConfigIntroStep); const goToSaveConfig = () => setAddSourceStep(AddSourceSteps.SaveConfigStep); From a07c47c652ae47d6bae35ee1edb011fda4bc853b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Tue, 29 Mar 2022 12:44:31 +0200 Subject: [PATCH 12/31] Set filter to undefined when it's empty on findExceptionLists method (#128455) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../src/api/index.ts | 2 +- .../lists/public/exceptions/api.test.ts | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/packages/kbn-securitysolution-list-api/src/api/index.ts b/packages/kbn-securitysolution-list-api/src/api/index.ts index 77c50fb32c299..a0361d044977c 100644 --- a/packages/kbn-securitysolution-list-api/src/api/index.ts +++ b/packages/kbn-securitysolution-list-api/src/api/index.ts @@ -231,7 +231,7 @@ const fetchExceptionLists = async ({ signal, }: ApiCallFetchExceptionListsProps): Promise => { const query = { - filter: filters, + filter: filters || undefined, namespace_type: namespaceTypes, page: pagination.page ? `${pagination.page}` : '1', per_page: pagination.perPage ? `${pagination.perPage}` : '20', diff --git a/x-pack/plugins/lists/public/exceptions/api.test.ts b/x-pack/plugins/lists/public/exceptions/api.test.ts index 65c11bfc1dfd0..923f4db19f62e 100644 --- a/x-pack/plugins/lists/public/exceptions/api.test.ts +++ b/x-pack/plugins/lists/public/exceptions/api.test.ts @@ -278,6 +278,31 @@ describe('Exceptions Lists API', () => { expect(exceptionResponse.data).toEqual([getExceptionListSchemaMock()]); }); + test('it returns expected exception lists when empty filter', async () => { + const exceptionResponse = await fetchExceptionLists({ + filters: '', + http: httpMock, + namespaceTypes: 'single,agnostic', + pagination: { + page: 1, + perPage: 20, + }, + signal: abortCtrl.signal, + }); + expect(httpMock.fetch).toHaveBeenCalledWith('/api/exception_lists/_find', { + method: 'GET', + query: { + namespace_type: 'single,agnostic', + page: '1', + per_page: '20', + sort_field: 'exception-list.created_at', + sort_order: 'desc', + }, + signal: abortCtrl.signal, + }); + expect(exceptionResponse.data).toEqual([getExceptionListSchemaMock()]); + }); + test('it returns error if response payload fails decode', async () => { const badPayload = getExceptionListSchemaMock(); // @ts-expect-error From 131a2892fb22b4a711155bb822408653e5ed0f0c Mon Sep 17 00:00:00 2001 From: Joe Reuter Date: Tue, 29 Mar 2022 12:49:51 +0200 Subject: [PATCH 13/31] [Lens] Add normalize_by_unit function and option (#128303) * add time scale function and option * add example to documentation * fixes * rename * fix test Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/lens/public/index.ts | 1 + .../definitions/calculations/index.ts | 2 + .../definitions/calculations/time_scale.tsx | 147 ++++++++++++++++++ .../definitions/formula/formula.test.tsx | 1 + .../definitions/formula/formula.tsx | 3 +- .../operations/definitions/index.ts | 4 + .../operations/index.ts | 1 + .../operations/operations.test.ts | 4 + .../public/indexpattern_datasource/types.ts | 1 + 9 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/time_scale.tsx diff --git a/x-pack/plugins/lens/public/index.ts b/x-pack/plugins/lens/public/index.ts index 5b1501410df26..4cdbe464bd302 100644 --- a/x-pack/plugins/lens/public/index.ts +++ b/x-pack/plugins/lens/public/index.ts @@ -66,6 +66,7 @@ export type { OverallSumIndexPatternColumn, FormulaPublicApi, StaticValueIndexPatternColumn, + TimeScaleIndexPatternColumn, } from './indexpattern_datasource/types'; export type { XYArgs, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/index.ts index 1ffbdea00b775..3a3de198d4205 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/index.ts @@ -25,3 +25,5 @@ export { overallMaxOperation, overallAverageOperation, } from './overall_metric'; +export type { TimeScaleIndexPatternColumn } from './time_scale'; +export { timeScaleOperation } from './time_scale'; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/time_scale.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/time_scale.tsx new file mode 100644 index 0000000000000..326d564ef4832 --- /dev/null +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/calculations/time_scale.tsx @@ -0,0 +1,147 @@ +/* + * 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 type { + FormattedIndexPatternColumn, + ReferenceBasedIndexPatternColumn, +} from '../column_types'; +import { getErrorsForDateReference } from './utils'; +import type { OperationDefinition } from '..'; +import { combineErrorMessages, getFormatFromPreviousColumn } from '../helpers'; +import { IndexPatternLayer } from '../../../types'; +import { getDisallowedPreviousShiftMessage } from '../../../time_shift_utils'; + +type OverallMetricIndexPatternColumn = FormattedIndexPatternColumn & + ReferenceBasedIndexPatternColumn & { + operationType: T; + }; + +export type OverallSumIndexPatternColumn = OverallMetricIndexPatternColumn<'overall_sum'>; +export type OverallMinIndexPatternColumn = OverallMetricIndexPatternColumn<'overall_min'>; +export type OverallMaxIndexPatternColumn = OverallMetricIndexPatternColumn<'overall_max'>; +export type OverallAverageIndexPatternColumn = OverallMetricIndexPatternColumn<'overall_average'>; + +export type TimeScaleIndexPatternColumn = FormattedIndexPatternColumn & + ReferenceBasedIndexPatternColumn & { + operationType: 'normalize_by_unit'; + params: { + unit?: string; + }; + }; + +export const timeScaleOperation: OperationDefinition = + { + type: 'normalize_by_unit', + priority: 1, + displayName: i18n.translate('xpack.lens.indexPattern.timeScale', { + defaultMessage: 'Normalize by unit', + }), + input: 'fullReference', + selectionStyle: 'hidden', + requiredReferences: [ + { + input: ['field', 'managedReference', 'fullReference'], + validateMetadata: (meta) => meta.dataType === 'number' && !meta.isBucketed, + }, + ], + operationParams: [{ name: 'unit', type: 'string', required: true }], + getPossibleOperation: () => { + return { + dataType: 'number', + isBucketed: false, + scale: 'ratio', + }; + }, + getDefaultLabel: (column, indexPattern, columns) => { + return 'normalize_by_unit'; + }, + toExpression: (layer, columnId) => { + const currentColumn = layer.columns[columnId] as unknown as TimeScaleIndexPatternColumn; + const buckets = layer.columnOrder.filter((colId) => layer.columns[colId].isBucketed); + const dateColumn = buckets.find( + (colId) => layer.columns[colId].operationType === 'date_histogram' + )!; + return [ + { + type: 'function', + function: 'lens_time_scale', + arguments: { + dateColumnId: [dateColumn], + inputColumnId: [currentColumn.references[0]], + outputColumnId: [columnId], + outputColumnName: [currentColumn.label], + targetUnit: [currentColumn.params.unit!], + }, + }, + ]; + }, + buildColumn: ({ referenceIds, previousColumn, layer, indexPattern }, columnParams) => { + return { + label: 'Normalize by unit', + dataType: 'number', + operationType: 'normalize_by_unit', + isBucketed: false, + scale: 'ratio', + references: referenceIds, + params: { + ...getFormatFromPreviousColumn(previousColumn), + unit: columnParams?.unit, + }, + }; + }, + isTransferable: () => { + return true; + }, + getErrorMessage: (layer: IndexPatternLayer, columnId: string) => { + return combineErrorMessages([ + getErrorsForDateReference( + layer, + columnId, + i18n.translate('xpack.lens.indexPattern.timeScale', { + defaultMessage: 'Normalize by unit', + }) + ), + getDisallowedPreviousShiftMessage(layer, columnId), + !(layer.columns[columnId] as TimeScaleIndexPatternColumn).params.unit + ? [ + i18n.translate('xpack.lens.indexPattern.timeScale.missingUnit', { + defaultMessage: 'No unit specified for normalize by unit.', + }), + ] + : [], + ['s', 'm', 'h', 'd'].indexOf( + (layer.columns[columnId] as TimeScaleIndexPatternColumn).params.unit || 's' + ) === -1 + ? [ + i18n.translate('xpack.lens.indexPattern.timeScale.wrongUnit', { + defaultMessage: 'Unknown unit specified, use s,m,h or d.', + }), + ] + : [], + ]); + }, + filterable: false, + shiftable: false, + documentation: { + section: 'calculation', + signature: i18n.translate('xpack.lens.indexPattern.time_scale', { + defaultMessage: 'metric: number, unit: s|m|h|d|w|M|y', + }), + description: i18n.translate('xpack.lens.indexPattern.time_scale.documentation.markdown', { + defaultMessage: ` + +This advanced function is useful for normalizing counts and sums to a specific time interval. It allows for integration with metrics that are stored already normalized to a specific time interval. + +This function can only be used if there's a date histogram function used in the current chart. + +Example: A ratio comparing an already normalized metric to another metric that needs to be normalized. +\`normalize_by_unit(counter_rate(max(system.diskio.write.bytes)), unit='s') / last_value(apache.status.bytes_per_second)\` + `, + }), + }, + }; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx index 0fb7f35beb02b..51e7d363ac39d 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.test.tsx @@ -343,6 +343,7 @@ describe('formula', () => { formula: 'moving_average(average(bytes), window=3)', }, references: [], + timeScale: 'd', }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx index 9bbd1588d29b6..1f0fbceff3d5b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/operations/definitions/formula/formula.tsx @@ -168,6 +168,7 @@ export const formulaOperation: OperationDefinition { @@ -181,6 +182,6 @@ export const formulaOperation: OperationDefinition { "operationType": "overall_average", "type": "fullReference", }, + Object { + "operationType": "normalize_by_unit", + "type": "fullReference", + }, Object { "field": "bytes", "operationType": "min", diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts index 5bb4d58ed20fa..5d518b4048ed0 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/types.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/types.ts @@ -37,6 +37,7 @@ export type { MathIndexPatternColumn, OverallSumIndexPatternColumn, StaticValueIndexPatternColumn, + TimeScaleIndexPatternColumn, } from './operations'; export type { FormulaPublicApi } from './operations/definitions/formula/formula_public_api'; From 53dde5f44e77300169eab7d34aa06f3f1b446250 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Tue, 29 Mar 2022 12:51:12 +0200 Subject: [PATCH 14/31] [Security Solution] Update user page deep links (#128722) * Update user page deep links * Fix a couple of code style issues introduced on #128375 https://github.com/elastic/kibana/pull/128375 --- .../security_solution/common/constants.ts | 7 +- .../public/app/deep_links/index.test.ts | 8 ++ .../public/app/deep_links/index.ts | 45 ++++++++++- .../users/components/all_users/index.tsx | 76 +++++++++---------- .../factory/users/all/query.all_users.dsl.ts | 4 +- 5 files changed, 93 insertions(+), 47 deletions(-) diff --git a/x-pack/plugins/security_solution/common/constants.ts b/x-pack/plugins/security_solution/common/constants.ts index 2e64c710aa41c..591c7d68e17cb 100644 --- a/x-pack/plugins/security_solution/common/constants.ts +++ b/x-pack/plugins/security_solution/common/constants.ts @@ -79,7 +79,6 @@ export const DEFAULT_THREAT_MATCH_QUERY = '@timestamp >= "now-30d/d"' as const; export enum SecurityPageName { administration = 'administration', alerts = 'alerts', - authentications = 'authentications', /* * Warning: Computed values are not permitted in an enum with string valued members * The 3 following Cases page names must match `CasesDeepLinkId` in x-pack/plugins/cases/public/common/navigation.ts @@ -92,7 +91,6 @@ export enum SecurityPageName { detectionAndResponse = 'detection_response', endpoints = 'endpoints', eventFilters = 'event_filters', - events = 'events', exceptions = 'exceptions', explore = 'explore', hostIsolationExceptions = 'host_isolation_exceptions', @@ -100,6 +98,8 @@ export enum SecurityPageName { hostsAnomalies = 'hosts-anomalies', hostsExternalAlerts = 'hosts-external_alerts', hostsRisk = 'hosts-risk', + hostsEvents = 'hosts-events', + hostsAuthentications = 'hosts-authentications', investigate = 'investigate', landing = 'get_started', network = 'network', @@ -116,9 +116,12 @@ export enum SecurityPageName { trustedApps = 'trusted_apps', uncommonProcesses = 'uncommon_processes', users = 'users', + usersAuthentications = 'users-authentications', usersAnomalies = 'users-anomalies', usersRisk = 'users-risk', sessions = 'sessions', + usersEvents = 'users-events', + usersExternalAlerts = 'users-external_alerts', } export const TIMELINES_PATH = '/timelines' as const; diff --git a/x-pack/plugins/security_solution/public/app/deep_links/index.test.ts b/x-pack/plugins/security_solution/public/app/deep_links/index.test.ts index 583f1f3ea9b0d..0676c516ede64 100644 --- a/x-pack/plugins/security_solution/public/app/deep_links/index.test.ts +++ b/x-pack/plugins/security_solution/public/app/deep_links/index.test.ts @@ -154,6 +154,14 @@ describe('deepLinks', () => { expect(findDeepLink(SecurityPageName.users, deepLinks)).toBeTruthy(); }); + it('should NOT return host authentications when enableExperimental.usersEnabled === true', () => { + const deepLinks = getDeepLinks({ + ...mockGlobalState.app.enableExperimental, + usersEnabled: true, + }); + expect(findDeepLink(SecurityPageName.hostsAuthentications, deepLinks)).toBeFalsy(); + }); + it('should return NO detection & Response link when enableExperimental.detectionResponseEnabled === false', () => { const deepLinks = getDeepLinks(mockGlobalState.app.enableExperimental); expect(findDeepLink(SecurityPageName.detectionAndResponse, deepLinks)).toBeFalsy(); diff --git a/x-pack/plugins/security_solution/public/app/deep_links/index.ts b/x-pack/plugins/security_solution/public/app/deep_links/index.ts index 2df243d9b2d41..6b417a984d899 100644 --- a/x-pack/plugins/security_solution/public/app/deep_links/index.ts +++ b/x-pack/plugins/security_solution/public/app/deep_links/index.ts @@ -68,7 +68,14 @@ type Feature = typeof FEATURE[keyof typeof FEATURE]; type SecuritySolutionDeepLink = AppDeepLink & { isPremium?: boolean; features?: Feature[]; + /** + * Displays deep link when feature flag is enabled. + */ experimentalKey?: keyof ExperimentalFeatures; + /** + * Hides deep link when feature flag is enabled. + */ + hideWhenExperimentalKey?: keyof ExperimentalFeatures; deepLinks?: SecuritySolutionDeepLink[]; }; @@ -186,11 +193,12 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ order: 9002, deepLinks: [ { - id: SecurityPageName.authentications, + id: SecurityPageName.hostsAuthentications, title: i18n.translate('xpack.securitySolution.search.hosts.authentications', { defaultMessage: 'Authentications', }), path: `${HOSTS_PATH}/authentications`, + hideWhenExperimentalKey: 'usersEnabled', }, { id: SecurityPageName.uncommonProcesses, @@ -200,7 +208,7 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ path: `${HOSTS_PATH}/uncommonProcesses`, }, { - id: SecurityPageName.events, + id: SecurityPageName.hostsEvents, title: i18n.translate('xpack.securitySolution.search.hosts.events', { defaultMessage: 'Events', }), @@ -293,6 +301,13 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ ], order: 9004, deepLinks: [ + { + id: SecurityPageName.usersAuthentications, + title: i18n.translate('xpack.securitySolution.search.users.authentications', { + defaultMessage: 'Authentications', + }), + path: `${USERS_PATH}/authentications`, + }, { id: SecurityPageName.usersAnomalies, title: i18n.translate('xpack.securitySolution.search.users.anomalies', { @@ -307,7 +322,21 @@ export const securitySolutionsDeepLinks: SecuritySolutionDeepLink[] = [ defaultMessage: 'Risk', }), path: `${USERS_PATH}/userRisk`, - isPremium: true, + experimentalKey: 'riskyUsersEnabled', + }, + { + id: SecurityPageName.usersEvents, + title: i18n.translate('xpack.securitySolution.search.users.events', { + defaultMessage: 'Events', + }), + path: `${USERS_PATH}/events`, + }, + { + id: SecurityPageName.usersExternalAlerts, + title: i18n.translate('xpack.securitySolution.search.users.externalAlerts', { + defaultMessage: 'External Alerts', + }), + path: `${USERS_PATH}/externalAlerts`, }, ], }, @@ -428,13 +457,21 @@ export function getDeepLinks( ): AppDeepLink[] { const filterDeepLinks = (securityDeepLinks: SecuritySolutionDeepLink[]): AppDeepLink[] => securityDeepLinks.reduce( - (deepLinks: AppDeepLink[], { isPremium, features, experimentalKey, ...deepLink }) => { + ( + deepLinks: AppDeepLink[], + { isPremium, features, experimentalKey, hideWhenExperimentalKey, ...deepLink } + ) => { if (licenseType && isPremium && !isPremiumLicense(licenseType)) { return deepLinks; } if (experimentalKey && !enableExperimental[experimentalKey]) { return deepLinks; } + + if (hideWhenExperimentalKey && enableExperimental[hideWhenExperimentalKey]) { + return deepLinks; + } + if (capabilities != null && !hasFeaturesCapability(features, capabilities)) { return deepLinks; } diff --git a/x-pack/plugins/security_solution/public/users/components/all_users/index.tsx b/x-pack/plugins/security_solution/public/users/components/all_users/index.tsx index 15626d0650ac8..9a00a637f551d 100644 --- a/x-pack/plugins/security_solution/public/users/components/all_users/index.tsx +++ b/x-pack/plugins/security_solution/public/users/components/all_users/index.tsx @@ -58,6 +58,44 @@ const rowItems: ItemsPerRow[] = [ }, ]; +const getUsersColumns = (): UsersTableColumns => [ + { + field: 'name', + name: i18n.USER_NAME, + truncateText: false, + sortable: true, + mobileOptions: { show: true }, + render: (name) => + getRowItemDraggables({ + rowItems: [name], + attrName: 'user.name', + idPrefix: `users-table-${name}-name`, + render: (item) => , + }), + }, + { + field: 'lastSeen', + name: i18n.LAST_SEEN, + sortable: true, + truncateText: false, + mobileOptions: { show: true }, + render: (lastSeen) => , + }, + { + field: 'domain', + name: i18n.DOMAIN, + sortable: false, + truncateText: false, + mobileOptions: { show: true }, + render: (domain) => + getRowItemDraggables({ + rowItems: [domain], + attrName: 'user.domain', + idPrefix: `users-table-${domain}-domain`, + }), + }, +]; + const UsersTableComponent: React.FC = ({ users, totalCount, @@ -146,41 +184,3 @@ const UsersTableComponent: React.FC = ({ UsersTableComponent.displayName = 'UsersTableComponent'; export const UsersTable = React.memo(UsersTableComponent); - -const getUsersColumns = (): UsersTableColumns => [ - { - field: 'name', - name: i18n.USER_NAME, - truncateText: false, - sortable: true, - mobileOptions: { show: true }, - render: (name) => - getRowItemDraggables({ - rowItems: [name], - attrName: 'user.name', - idPrefix: `users-table-${name}-name`, - render: (item) => , - }), - }, - { - field: 'lastSeen', - name: i18n.LAST_SEEN, - sortable: true, - truncateText: false, - mobileOptions: { show: true }, - render: (lastSeen) => , - }, - { - field: 'domain', - name: i18n.DOMAIN, - sortable: false, - truncateText: false, - mobileOptions: { show: true }, - render: (domain) => - getRowItemDraggables({ - rowItems: [domain], - attrName: 'user.domain', - idPrefix: `users-table-${domain}-domain`, - }), - }, -]; diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/all/query.all_users.dsl.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/all/query.all_users.dsl.ts index ee98c92d2ac6b..850a590fdfe41 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/all/query.all_users.dsl.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/users/all/query.all_users.dsl.ts @@ -37,8 +37,6 @@ export const buildUsersQuery = ({ }, ]; - const agg = { user_count: { cardinality: { field: 'user.name' } } }; - const dslQuery = { allow_no_indices: true, index: defaultIndex, @@ -47,7 +45,7 @@ export const buildUsersQuery = ({ body: { ...(!isEmpty(docValueFields) ? { docvalue_fields: docValueFields } : {}), aggregations: { - ...agg, + user_count: { cardinality: { field: 'user.name' } }, user_data: { terms: { size: querySize, field: 'user.name', order: getQueryOrder(sort) }, aggs: { From 17086ad6ceb726411a99c2a41477f6e89359b9a1 Mon Sep 17 00:00:00 2001 From: Georgii Gorbachev Date: Tue, 29 Mar 2022 13:42:36 +0200 Subject: [PATCH 15/31] [Security Solution][Detections] Adds UI for bulk applying timeline template (#128691) **Addresses:** https://github.com/elastic/kibana/issues/93083, https://github.com/elastic/security-team/issues/2078 (internal) ## Summary This PR adds a UI for applying a timeline template to multiple rules in bulk. - A new bulk actions menu item to the Rule Management table. - A new form flyout for applying a timeline template. - Some glue code to connect them. There are a few issues that I'd like to address in a follow-up PR after the FF: 1. Resetting already applied templates to `None` doesn't work because of the way the `patchRules` function works. This is a known bug in this implementation. We will need to replace `patchRules` with something else for bulk editing actions. 2. I need to add some test coverage. Other notes: - I changed some copies to hopefully make it a little bit clearer. Let me know if you want to rephrase. ## Screenshots ![](https://puu.sh/IRpnL/9abe2ce1b5.png) The template selector doesn't look good on a smaller screen: ![](https://puu.sh/IRpyP/eb7bebabc7.png) --- .../all/bulk_actions/bulk_edit_flyout.tsx | 4 + .../forms/bulk_edit_form_wrapper.tsx | 14 +-- .../forms/timeline_template_form.tsx | 102 ++++++++++++++++++ .../rules/all/bulk_actions/translations.tsx | 50 +++++++++ .../all/bulk_actions/use_bulk_actions.tsx | 10 ++ .../detection_engine/rules/translations.ts | 7 ++ .../rules/bulk_action_edit.ts | 11 +- 7 files changed, 187 insertions(+), 11 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/forms/timeline_template_form.tsx create mode 100644 x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/translations.tsx diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/bulk_edit_flyout.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/bulk_edit_flyout.tsx index a6b5f664fc7cd..07967ae53a041 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/bulk_edit_flyout.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/bulk_edit_flyout.tsx @@ -14,6 +14,7 @@ import { import { IndexPatternsForm } from './forms/index_patterns_form'; import { TagsForm } from './forms/tags_form'; +import { TimelineTemplateForm } from './forms/timeline_template_form'; interface BulkEditFlyoutProps { onClose: () => void; @@ -35,6 +36,9 @@ const BulkEditFlyoutComponent = ({ editAction, tags, ...props }: BulkEditFlyoutP case BulkActionEditType.set_tags: return ; + case BulkActionEditType.set_timeline: + return ; + default: return null; } diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/forms/bulk_edit_form_wrapper.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/forms/bulk_edit_form_wrapper.tsx index a56a4fe3d159e..49d4487808740 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/forms/bulk_edit_form_wrapper.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/forms/bulk_edit_form_wrapper.tsx @@ -24,19 +24,21 @@ import { Form, FormHook } from '../../../../../../../shared_imports'; import * as i18n from '../../../translations'; interface BulkEditFormWrapperProps { - onClose: () => void; - onSubmit: () => void; - title: string; form: FormHook; + title: string; + banner?: React.ReactNode; children: React.ReactNode; + onClose: () => void; + onSubmit: () => void; } const BulkEditFormWrapperComponent: FC = ({ form, + title, + banner, + children, onClose, onSubmit, - children, - title, }) => { const simpleFlyoutTitleId = useGeneratedHtmlId({ prefix: 'RulesBulkEditForm', @@ -50,7 +52,7 @@ const BulkEditFormWrapperComponent: FC = ({

{title}

- +
{children}
diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/forms/timeline_template_form.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/forms/timeline_template_form.tsx new file mode 100644 index 0000000000000..8e67b2711a278 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/forms/timeline_template_form.tsx @@ -0,0 +1,102 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React, { useCallback } from 'react'; +import { EuiCallOut } from '@elastic/eui'; + +import { useForm, UseField, FormSchema } from '../../../../../../../shared_imports'; +import { PickTimeline } from '../../../../../../components/rules/pick_timeline'; +import { + BulkActionEditType, + BulkActionEditPayload, +} from '../../../../../../../../common/detection_engine/schemas/common/schemas'; + +import { BulkEditFormWrapper } from './bulk_edit_form_wrapper'; +import { bulkApplyTimelineTemplate as i18n } from '../translations'; + +export interface TimelineTemplateFormData { + timeline: { + id: string | null; + title: string; + }; +} + +const formSchema: FormSchema = { + timeline: { + label: i18n.TEMPLATE_SELECTOR_LABEL, + helpText: i18n.TEMPLATE_SELECTOR_HELP_TEXT, + }, +}; + +const defaultFormData: TimelineTemplateFormData = { + timeline: { + id: null, + title: i18n.TEMPLATE_SELECTOR_DEFAULT_VALUE, + }, +}; + +interface TimelineTemplateFormProps { + rulesCount: number; + onClose: () => void; + onConfirm: (bulkActionEditPayload: BulkActionEditPayload) => void; +} + +const TimelineTemplateFormComponent = (props: TimelineTemplateFormProps) => { + const { rulesCount, onClose, onConfirm } = props; + + const { form } = useForm({ + schema: formSchema, + defaultValue: defaultFormData, + }); + + const handleSubmit = useCallback(async () => { + const { data, isValid } = await form.submit(); + if (!isValid) { + return; + } + + const timelineId = data.timeline.id || ''; + const timelineTitle = timelineId ? data.timeline.title : ''; + + onConfirm({ + type: BulkActionEditType.set_timeline, + value: { + timeline_id: timelineId, + timeline_title: timelineTitle, + }, + }); + }, [form, onConfirm]); + + const warningCallout = ( + + {i18n.warningCalloutMessage(rulesCount)} + + ); + + return ( + + {/* Timeline template selector */} + + + ); +}; + +export const TimelineTemplateForm = React.memo(TimelineTemplateFormComponent); +TimelineTemplateForm.displayName = 'TimelineTemplateForm'; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/translations.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/translations.tsx new file mode 100644 index 0000000000000..d35a89484f264 --- /dev/null +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/translations.tsx @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; + +export const bulkApplyTimelineTemplate = { + FORM_TITLE: i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.edit.applyTimelineTemplate.formTitle', + { + defaultMessage: 'Apply timeline template', + } + ), + + TEMPLATE_SELECTOR_LABEL: i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.edit.applyTimelineTemplate.templateSelectorLabel', + { + defaultMessage: 'Apply timeline template to selected rules', + } + ), + + TEMPLATE_SELECTOR_HELP_TEXT: i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.edit.applyTimelineTemplate.templateSelectorHelpText', + { + defaultMessage: + 'Select which timeline to apply to selected rules when investigating generated alerts.', + } + ), + + TEMPLATE_SELECTOR_DEFAULT_VALUE: i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.edit.applyTimelineTemplate.templateSelectorDefaultValue', + { + defaultMessage: 'None', + } + ), + + warningCalloutMessage: (rulesCount: number): JSX.Element => ( + + ), +}; diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx index 6bd7cfc67f308..9aa175002af7b 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/all/bulk_actions/use_bulk_actions.tsx @@ -307,6 +307,16 @@ export const useBulkActions = ({ disabled: isEditDisabled, panel: 1, }, + { + key: i18n.BULK_ACTION_APPLY_TIMELINE_TEMPLATE, + name: i18n.BULK_ACTION_APPLY_TIMELINE_TEMPLATE, + 'data-test-subj': 'applyTimelineTemplateBulk', + disabled: isEditDisabled, + onClick: handleBulkEdit(BulkActionEditType.set_timeline), + toolTipContent: missingActionPrivileges ? i18n.EDIT_RULE_SETTINGS_TOOLTIP : undefined, + toolTipPosition: 'right', + icon: undefined, + }, { key: i18n.BULK_ACTION_EXPORT, name: i18n.BULK_ACTION_EXPORT, diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts index f93ca2f48d2db..f99ebc2c72c26 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts @@ -193,6 +193,13 @@ export const BULK_ACTION_DELETE_TAGS = i18n.translate( } ); +export const BULK_ACTION_APPLY_TIMELINE_TEMPLATE = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.applyTimelineTemplateTitle', + { + defaultMessage: 'Apply timeline template', + } +); + export const BULK_ACTION_MENU_TITLE = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.allRules.bulkActions.contextMenuTitle', { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/bulk_action_edit.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/bulk_action_edit.ts index 8df66dcc3b191..5133d1604d621 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/rules/bulk_action_edit.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rules/bulk_action_edit.ts @@ -78,11 +78,12 @@ export const applyBulkActionEditToRule = ( // timeline actions case BulkActionEditType.set_timeline: - rule.params = { - ...rule.params, - timelineId: action.value.timeline_id, - timelineTitle: action.value.timeline_title, - }; + const timelineId = action.value.timeline_id.trim() || undefined; + const timelineTitle = timelineId ? action.value.timeline_title : undefined; + + rule.params.timelineId = timelineId; + rule.params.timelineTitle = timelineTitle; + break; } return rule; From 92aea763cbc4c68bd86b601711c7569aee48f0e3 Mon Sep 17 00:00:00 2001 From: Oliver Gupte Date: Tue, 29 Mar 2022 08:10:00 -0400 Subject: [PATCH 16/31] [APM] ensure rum_allow_origins setting only saves valid YAML strings (#128703) (#128704) --- .../fleet/create_cloud_apm_package_policy.ts | 3 ++- .../get_apm_package_policy_definition.ts | 23 +++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts b/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts index 797bce77facdb..670932ea6dbbd 100644 --- a/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts +++ b/x-pack/plugins/apm/server/routes/fleet/create_cloud_apm_package_policy.ts @@ -23,6 +23,7 @@ import { import { getApmPackagePolicyDefinition } from './get_apm_package_policy_definition'; import { Setup } from '../../lib/helpers/setup_request'; import { mergePackagePolicyWithApm } from './merge_package_policy_with_apm'; +import { ELASTIC_CLOUD_APM_AGENT_POLICY_ID } from '../../../common/fleet'; export async function createCloudApmPackgePolicy({ cloudPluginSetup, @@ -65,7 +66,7 @@ export async function createCloudApmPackgePolicy({ savedObjectsClient, esClient, mergedAPMPackagePolicy, - { force: true, bumpRevision: true } + { id: ELASTIC_CLOUD_APM_AGENT_POLICY_ID, force: true, bumpRevision: true } ); logger.info(`Fleet migration on Cloud - apmPackagePolicy create end`); return apmPackagePolicy; diff --git a/x-pack/plugins/apm/server/routes/fleet/get_apm_package_policy_definition.ts b/x-pack/plugins/apm/server/routes/fleet/get_apm_package_policy_definition.ts index 85ac03697019c..28b40447136ce 100644 --- a/x-pack/plugins/apm/server/routes/fleet/get_apm_package_policy_definition.ts +++ b/x-pack/plugins/apm/server/routes/fleet/get_apm_package_policy_definition.ts @@ -5,12 +5,12 @@ * 2.0. */ +import yaml from 'js-yaml'; import { KibanaRequest } from 'kibana/server'; import { RegistryVarsEntry } from '../../../../fleet/common'; import { POLICY_ELASTIC_AGENT_ON_CLOUD, INPUT_VAR_NAME_TO_SCHEMA_PATH, - ELASTIC_CLOUD_APM_AGENT_POLICY_ID, } from '../../../common/fleet'; import { APMPluginSetupDependencies, @@ -36,7 +36,6 @@ export async function getApmPackagePolicyDefinition({ }); return { - id: ELASTIC_CLOUD_APM_AGENT_POLICY_ID, name: 'Elastic APM', namespace: 'default', enabled: true, @@ -73,6 +72,9 @@ function getApmPackageInputVars({ }): Record { const overrideValues: Record = { url: cloudPluginSetup?.apm?.url, // overrides 'apm-server.url' to be the cloud APM host + rum_allow_origins: ensureValidMultiText( + apmServerSchema[INPUT_VAR_NAME_TO_SCHEMA_PATH.rum_allow_origins] + ), // fixes issue where "*" needs to be wrapped in quotes to be parsed as a YAML string }; return policyTemplateInputVars.reduce((acc, registryVarsEntry) => { @@ -90,3 +92,20 @@ function getApmPackageInputVars({ }; }, {}); } + +function ensureValidMultiText(textMultiValue: string[] | undefined) { + if (!textMultiValue) { + return undefined; + } + return textMultiValue.map(escapeInvalidYamlString); +} +function escapeInvalidYamlString(yamlString: string) { + try { + yaml.load(yamlString); + } catch (error) { + if (error instanceof yaml.YAMLException) { + return `"${yamlString}"`; + } + } + return yamlString; +} From 99ec409646dd3878b3352b8139c3098887aa1469 Mon Sep 17 00:00:00 2001 From: Katerina Patticha Date: Tue, 29 Mar 2022 14:24:13 +0200 Subject: [PATCH 17/31] Fix synthrace command (#128729) --- x-pack/plugins/apm/dev_docs/local_setup.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/apm/dev_docs/local_setup.md b/x-pack/plugins/apm/dev_docs/local_setup.md index f021f41b17c80..e41ee4390d58c 100644 --- a/x-pack/plugins/apm/dev_docs/local_setup.md +++ b/x-pack/plugins/apm/dev_docs/local_setup.md @@ -29,7 +29,7 @@ node ./scripts/es_archiver load "x-pack/plugins/apm/ftr_e2e/cypress/fixtures/es_ **Run Synthtrace** ``` -node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts --target=http://elastic:changeme@localhost:9200 +node packages/elastic-apm-synthtrace/src/scripts/run packages/elastic-apm-synthtrace/src/scripts/examples/01_simple_trace.ts --target=http://localhost:9200 --username=elastic --password=changeme ``` **Connect Kibana to ES** From 569e4e8458d91f05a9ae3c3f8192640230ac25c1 Mon Sep 17 00:00:00 2001 From: Tiago Costa Date: Tue, 29 Mar 2022 13:37:53 +0100 Subject: [PATCH 18/31] skip flaky suite (#127077) --- .../server/integration_tests/cloud_preconfiguration.test.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts b/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts index b55a95aec6103..5fa3bb118b0ed 100644 --- a/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/integration_tests/cloud_preconfiguration.test.ts @@ -108,7 +108,8 @@ describe.skip('Fleet preconfiguration reset', () => { await stopServers(); }); - describe('Preconfigred cloud policy', () => { + // FLAKY: https://github.com/elastic/kibana/issues/127077 + describe.skip('Preconfigred cloud policy', () => { it('Works and preconfigure correctly agent policies', async () => { const agentPolicies = await kbnServer.coreStart.savedObjects .createInternalRepository() From 91394d41e7d9cbe2eefa242aeb21c8523a369111 Mon Sep 17 00:00:00 2001 From: Dmitry Tomashevich <39378793+Dmitriynj@users.noreply.github.com> Date: Tue, 29 Mar 2022 17:48:49 +0500 Subject: [PATCH 19/31] [Graph] Clean up deprecated APIs (#128579) * [Discover] clean up deprecated apis * [Graph] apply suggestions * [Discover] replace the last DataView occurrence Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/graph/public/application.tsx | 4 ++-- .../graph/public/components/inspect_panel.tsx | 4 ++-- .../graph/public/components/search_bar.test.tsx | 7 ++++--- .../graph/public/components/search_bar.tsx | 15 ++++++--------- .../workspace_layout/workspace_layout.tsx | 6 +++--- .../graph/public/services/index_pattern_cache.ts | 6 +++--- .../services/persistence/deserialize.test.ts | 6 +++--- .../public/services/persistence/deserialize.ts | 15 +++++---------- .../public/state_management/datasource.sagas.ts | 4 ++-- .../public/state_management/datasource.test.ts | 4 ++-- .../graph/public/state_management/mocks.ts | 4 ++-- .../graph/public/state_management/persistence.ts | 4 ++-- x-pack/plugins/graph/public/types/app_state.ts | 4 ++-- 13 files changed, 38 insertions(+), 45 deletions(-) diff --git a/x-pack/plugins/graph/public/application.tsx b/x-pack/plugins/graph/public/application.tsx index 235c9aa843797..adc396965f6a7 100644 --- a/x-pack/plugins/graph/public/application.tsx +++ b/x-pack/plugins/graph/public/application.tsx @@ -21,7 +21,7 @@ import { } from 'kibana/public'; import ReactDOM from 'react-dom'; import React from 'react'; -import { DataPlugin, IndexPatternsContract } from '../../../../src/plugins/data/public'; +import { DataPlugin, DataViewsContract } from '../../../../src/plugins/data/public'; import { LicensingPluginStart } from '../../licensing/public'; import { checkLicense } from '../common/check_license'; import { NavigationPublicPluginStart as NavigationStart } from '../../../../src/plugins/navigation/public'; @@ -52,7 +52,7 @@ export interface GraphDependencies { licensing: LicensingPluginStart; chrome: ChromeStart; toastNotifications: ToastsStart; - indexPatterns: IndexPatternsContract; + indexPatterns: DataViewsContract; data: ReturnType; savedObjectsClient: SavedObjectsClientContract; addBasePath: (url: string) => string; diff --git a/x-pack/plugins/graph/public/components/inspect_panel.tsx b/x-pack/plugins/graph/public/components/inspect_panel.tsx index 5a0ad8b5f291c..6881a750f76ed 100644 --- a/x-pack/plugins/graph/public/components/inspect_panel.tsx +++ b/x-pack/plugins/graph/public/components/inspect_panel.tsx @@ -9,12 +9,12 @@ import React, { useMemo, useState } from 'react'; import { EuiTab, EuiTabs, EuiText } from '@elastic/eui'; import { monaco, XJsonLang } from '@kbn/monaco'; import { FormattedMessage } from '@kbn/i18n-react'; -import { IndexPattern } from '../../../../../src/plugins/data/public'; import { CodeEditor } from '../../../../../src/plugins/kibana_react/public'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; interface InspectPanelProps { showInspect: boolean; - indexPattern?: IndexPattern; + indexPattern?: DataView; lastRequest?: string; lastResponse?: string; } diff --git a/x-pack/plugins/graph/public/components/search_bar.test.tsx b/x-pack/plugins/graph/public/components/search_bar.test.tsx index 72f95ecb0dc10..7feab56b2e272 100644 --- a/x-pack/plugins/graph/public/components/search_bar.test.tsx +++ b/x-pack/plugins/graph/public/components/search_bar.test.tsx @@ -17,7 +17,8 @@ import { SavedObjectsStart, } from 'kibana/public'; import { act } from 'react-dom/test-utils'; -import { IndexPattern, QueryStringInput } from '../../../../../src/plugins/data/public'; +import { QueryStringInput } from '../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public'; import { I18nProvider, InjectedIntl } from '@kbn/i18n-react'; @@ -87,12 +88,12 @@ describe('search_bar', () => { const defaultProps = { isLoading: false, indexPatternProvider: { - get: jest.fn(() => Promise.resolve({ fields: [] } as unknown as IndexPattern)), + get: jest.fn(() => Promise.resolve({ fields: [] } as unknown as DataView)), }, confirmWipeWorkspace: (callback: () => void) => { callback(); }, - onIndexPatternChange: (indexPattern?: IndexPattern) => { + onIndexPatternChange: (indexPattern?: DataView) => { instance.setProps({ ...defaultProps, currentIndexPattern: indexPattern, diff --git a/x-pack/plugins/graph/public/components/search_bar.tsx b/x-pack/plugins/graph/public/components/search_bar.tsx index 0760fb4fd2c13..89a82b5eb8483 100644 --- a/x-pack/plugins/graph/public/components/search_bar.tsx +++ b/x-pack/plugins/graph/public/components/search_bar.tsx @@ -10,6 +10,7 @@ import React, { useState, useEffect } from 'react'; import { i18n } from '@kbn/i18n'; import { connect } from 'react-redux'; +import { toElasticsearchQuery, fromKueryExpression } from '@kbn/es-query'; import { IndexPatternSavedObject, IndexPatternProvider, WorkspaceField } from '../types'; import { openSourceModal } from '../services/source_modal'; import { @@ -23,19 +24,18 @@ import { import { useKibana } from '../../../../../src/plugins/kibana_react/public'; import { - IndexPattern, QueryStringInput, IDataPluginServices, Query, - esKuery, } from '../../../../../src/plugins/data/public'; import { TooltipWrapper } from './tooltip_wrapper'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; export interface SearchBarProps { isLoading: boolean; urlQuery: string | null; - currentIndexPattern?: IndexPattern; - onIndexPatternChange: (indexPattern?: IndexPattern) => void; + currentIndexPattern?: DataView; + onIndexPatternChange: (indexPattern?: DataView) => void; confirmWipeWorkspace: ( onConfirm: () => void, text?: string, @@ -51,12 +51,9 @@ export interface SearchBarStateProps { submit: (searchTerm: string) => void; } -function queryToString(query: Query, indexPattern: IndexPattern) { +function queryToString(query: Query, indexPattern: DataView) { if (query.language === 'kuery' && typeof query.query === 'string') { - const dsl = esKuery.toElasticsearchQuery( - esKuery.fromKueryExpression(query.query as string), - indexPattern - ); + const dsl = toElasticsearchQuery(fromKueryExpression(query.query as string), indexPattern); // JSON representation of query will be handled by existing logic. // TODO clean this up and handle it in the data fetch layer once // it moved to typescript. diff --git a/x-pack/plugins/graph/public/components/workspace_layout/workspace_layout.tsx b/x-pack/plugins/graph/public/components/workspace_layout/workspace_layout.tsx index 5426ae9228518..3e7ff634eef0e 100644 --- a/x-pack/plugins/graph/public/components/workspace_layout/workspace_layout.tsx +++ b/x-pack/plugins/graph/public/components/workspace_layout/workspace_layout.tsx @@ -17,7 +17,7 @@ import { workspaceInitializedSelector, } from '../../state_management'; import { FieldManager } from '../field_manager'; -import { IndexPattern } from '../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../src/plugins/data_views/public'; import { ControlType, IndexPatternProvider, @@ -89,7 +89,7 @@ export const WorkspaceLayoutComponent = ({ sharingSavedObjectProps, spaces, }: WorkspaceLayoutProps & WorkspaceLayoutStateProps) => { - const [currentIndexPattern, setCurrentIndexPattern] = useState(); + const [currentIndexPattern, setCurrentIndexPattern] = useState(); const [showInspect, setShowInspect] = useState(false); const [pickerOpen, setPickerOpen] = useState(false); const [mergeCandidates, setMergeCandidates] = useState([]); @@ -112,7 +112,7 @@ export const WorkspaceLayoutComponent = ({ }, []); const onIndexPatternChange = useCallback( - (indexPattern?: IndexPattern) => setCurrentIndexPattern(indexPattern), + (indexPattern?: DataView) => setCurrentIndexPattern(indexPattern), [] ); diff --git a/x-pack/plugins/graph/public/services/index_pattern_cache.ts b/x-pack/plugins/graph/public/services/index_pattern_cache.ts index ddf630388a4f3..d6156bc9d0626 100644 --- a/x-pack/plugins/graph/public/services/index_pattern_cache.ts +++ b/x-pack/plugins/graph/public/services/index_pattern_cache.ts @@ -6,12 +6,12 @@ */ import { IndexPatternProvider } from '../types'; -import { IndexPattern } from '../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; export function createCachedIndexPatternProvider( - indexPatternGetter: (id: string) => Promise + indexPatternGetter: (id: string) => Promise ): IndexPatternProvider { - const cache = new Map(); + const cache = new Map(); return { get: async (id: string) => { diff --git a/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts b/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts index 31826c3b3a747..cc180065d3aca 100644 --- a/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts +++ b/x-pack/plugins/graph/public/services/persistence/deserialize.test.ts @@ -9,7 +9,7 @@ import { GraphWorkspaceSavedObject, IndexPatternSavedObject, Workspace } from '. import { migrateLegacyIndexPatternRef, savedWorkspaceToAppState, mapFields } from './deserialize'; import { createWorkspace } from '../../services/workspace/graph_client_workspace'; import { outlinkEncoders } from '../../helpers/outlink_encoders'; -import { IndexPattern } from '../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../src/plugins/data_views/public'; describe('deserialize', () => { let savedWorkspace: GraphWorkspaceSavedObject; @@ -124,7 +124,7 @@ describe('deserialize', () => { { name: 'field2', type: 'string', aggregatable: true, isMapped: true }, { name: 'field3', type: 'string', aggregatable: true, isMapped: true }, ], - } as IndexPattern, + } as DataView, workspace ); } @@ -247,7 +247,7 @@ describe('deserialize', () => { { name: 'runtimeField', type: 'string', aggregatable: true, isMapped: false }, { name: 'field3', type: 'string', aggregatable: true, isMapped: true }, ], - } as IndexPattern; + } as DataView; expect(mapFields(indexPattern).map(({ name }) => name)).toEqual([ 'field1', 'field2', diff --git a/x-pack/plugins/graph/public/services/persistence/deserialize.ts b/x-pack/plugins/graph/public/services/persistence/deserialize.ts index d76a07ab0fc32..1223c03b6f6c1 100644 --- a/x-pack/plugins/graph/public/services/persistence/deserialize.ts +++ b/x-pack/plugins/graph/public/services/persistence/deserialize.ts @@ -25,10 +25,8 @@ import { colorChoices, iconChoicesByClass, } from '../../helpers/style_choices'; -import { - IndexPattern, - indexPatterns as indexPatternsUtils, -} from '../../../../../../src/plugins/data/public'; +import { indexPatterns as indexPatternsUtils } from '../../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../../src/plugins/data_views/public'; const defaultAdvancedSettings: AdvancedSettings = { useSignificance: true, @@ -98,7 +96,7 @@ export function lookupIndexPatternId(savedWorkspace: GraphWorkspaceSavedObject) } // returns all graph fields mapped out of the index pattern -export function mapFields(indexPattern: IndexPattern): WorkspaceField[] { +export function mapFields(indexPattern: DataView): WorkspaceField[] { const blockedFieldNames = ['_id', '_index', '_score', '_source', '_type']; const defaultHopSize = 5; @@ -131,10 +129,7 @@ export function mapFields(indexPattern: IndexPattern): WorkspaceField[] { }); } -function getFieldsWithWorkspaceSettings( - indexPattern: IndexPattern, - selectedFields: SerializedField[] -) { +function getFieldsWithWorkspaceSettings(indexPattern: DataView, selectedFields: SerializedField[]) { const allFields = mapFields(indexPattern); // merge in selected information into all fields @@ -216,7 +211,7 @@ export function makeNodeId(field: string, term: string) { export function savedWorkspaceToAppState( savedWorkspace: GraphWorkspaceSavedObject, - indexPattern: IndexPattern, + indexPattern: DataView, workspaceInstance: Workspace ): { urlTemplates: UrlTemplate[]; diff --git a/x-pack/plugins/graph/public/state_management/datasource.sagas.ts b/x-pack/plugins/graph/public/state_management/datasource.sagas.ts index 55e23c5e7c7c1..bbab3cd13b7a9 100644 --- a/x-pack/plugins/graph/public/state_management/datasource.sagas.ts +++ b/x-pack/plugins/graph/public/state_management/datasource.sagas.ts @@ -18,7 +18,7 @@ import { setDatasource, requestDatasource, } from './datasource'; -import { IndexPattern } from '../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; /** * Saga loading field information when the datasource is switched. This will overwrite current settings @@ -34,7 +34,7 @@ export const datasourceSaga = ({ }: GraphStoreDependencies) => { function* fetchFields(action: Action) { try { - const indexPattern: IndexPattern = yield call(indexPatternProvider.get, action.payload.id); + const indexPattern: DataView = yield call(indexPatternProvider.get, action.payload.id); yield put(loadFields(mapFields(indexPattern))); yield put(datasourceLoaded()); const advancedSettings = settingsSelector(yield select()); diff --git a/x-pack/plugins/graph/public/state_management/datasource.test.ts b/x-pack/plugins/graph/public/state_management/datasource.test.ts index 00efe0c154732..ab37ed76ac08b 100644 --- a/x-pack/plugins/graph/public/state_management/datasource.test.ts +++ b/x-pack/plugins/graph/public/state_management/datasource.test.ts @@ -11,7 +11,7 @@ import { datasourceSelector, requestDatasource } from './datasource'; import { datasourceSaga } from './datasource.sagas'; import { fieldsSelector } from './fields'; import { updateSettings } from './advanced_settings'; -import { IndexPattern } from '../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; const waitForPromise = () => new Promise((r) => setTimeout(r)); @@ -27,7 +27,7 @@ describe('datasource saga', () => { Promise.resolve({ title: 'test-pattern', getNonScriptedFields: () => [{ name: 'field1', type: 'string', isMapped: true }], - } as IndexPattern) + } as DataView) ), }, }, diff --git a/x-pack/plugins/graph/public/state_management/mocks.ts b/x-pack/plugins/graph/public/state_management/mocks.ts index 906bcde9070fc..06f9fe52f936a 100644 --- a/x-pack/plugins/graph/public/state_management/mocks.ts +++ b/x-pack/plugins/graph/public/state_management/mocks.ts @@ -16,7 +16,7 @@ import { createStore, applyMiddleware, AnyAction } from 'redux'; import { ChromeStart } from 'kibana/public'; import { GraphStoreDependencies, createRootReducer, GraphStore, GraphState } from './store'; import { Workspace } from '../types'; -import { IndexPattern } from '../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; export interface MockedGraphEnvironment { store: GraphStore; @@ -63,7 +63,7 @@ export function createMockGraphStore({ if (id === 'missing-dataview') { throw Error('No data view with this id'); } - return { id: '123', title: 'test-pattern' } as unknown as IndexPattern; + return { id: '123', title: 'test-pattern' } as unknown as DataView; }), }, I18nContext: jest diff --git a/x-pack/plugins/graph/public/state_management/persistence.ts b/x-pack/plugins/graph/public/state_management/persistence.ts index d1e038bbb2102..d043df2510ed6 100644 --- a/x-pack/plugins/graph/public/state_management/persistence.ts +++ b/x-pack/plugins/graph/public/state_management/persistence.ts @@ -25,7 +25,7 @@ import { updateMetaData, metaDataSelector } from './meta_data'; import { openSaveModal, SaveWorkspaceHandler } from '../services/save_modal'; import { getEditPath } from '../services/url'; import { saveSavedWorkspace } from '../helpers/saved_workspace_utils'; -import type { IndexPattern } from '../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; export interface LoadSavedWorkspacePayload { indexPatterns: IndexPatternSavedObject[]; @@ -68,7 +68,7 @@ export const loadingSaga = ({ const selectedIndexPatternId = lookupIndexPatternId(savedWorkspace); let indexPattern; try { - indexPattern = (yield call(indexPatternProvider.get, selectedIndexPatternId)) as IndexPattern; + indexPattern = (yield call(indexPatternProvider.get, selectedIndexPatternId)) as DataView; } catch (e) { notifications.toasts.addDanger( i18n.translate('xpack.graph.loadWorkspace.missingDataViewErrorMessage', { diff --git a/x-pack/plugins/graph/public/types/app_state.ts b/x-pack/plugins/graph/public/types/app_state.ts index 1ec21c4991a1b..0d707cef9543b 100644 --- a/x-pack/plugins/graph/public/types/app_state.ts +++ b/x-pack/plugins/graph/public/types/app_state.ts @@ -8,7 +8,7 @@ import { SimpleSavedObject } from 'src/core/public'; import { FontawesomeIcon } from '../helpers/style_choices'; import { OutlinkEncoder } from '../helpers/outlink_encoders'; -import type { IndexPattern } from '../../../../../src/plugins/data/public'; +import type { DataView } from '../../../../../src/plugins/data_views/public'; export interface UrlTemplate { url: string; @@ -41,5 +41,5 @@ export interface AdvancedSettings { export type IndexPatternSavedObject = SimpleSavedObject<{ title: string }>; export interface IndexPatternProvider { - get(id: string): Promise; + get(id: string): Promise; } From bc6a6e444ff12a37b7b267e0eb1a9302d2cbafb0 Mon Sep 17 00:00:00 2001 From: Sandra G Date: Tue, 29 Mar 2022 09:04:56 -0400 Subject: [PATCH 20/31] [Stack Monitoring] add monitoring.ui.elasticsearch.serviceAccountToken to docs (#128488) * monitoring.ui.elasticsearch.serviceAccountToken to docs * update description * update * update to make clearer * Update docs/settings/monitoring-settings.asciidoc Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> * Update docs/settings/monitoring-settings.asciidoc Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Joe Portner <5295965+jportner@users.noreply.github.com> --- docs/settings/monitoring-settings.asciidoc | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/settings/monitoring-settings.asciidoc b/docs/settings/monitoring-settings.asciidoc index 8b469b1a90194..e78aeb6bac00b 100644 --- a/docs/settings/monitoring-settings.asciidoc +++ b/docs/settings/monitoring-settings.asciidoc @@ -50,10 +50,10 @@ cluster. `monitoring.ui.elasticsearch.username`:: Specifies the username used by {kib} monitoring to establish a persistent connection -in {kib} to the {es} monitoring cluster and to verify licensing status on the {es} -monitoring cluster. +in {kib} to the {es} monitoring cluster and to verify licensing status on the {es} +monitoring cluster when using `monitoring.ui.elasticsearch.hosts`. + -Every other request performed by *{stack-monitor-app}* to the monitoring {es} +All other requests performed by *{stack-monitor-app}* to the monitoring {es} cluster uses the authenticated user's credentials, which must be the same on both the {es} monitoring cluster and the {es} production cluster. + @@ -62,14 +62,17 @@ If not set, {kib} uses the value of the <> setting. +`monitoring.ui.elasticsearch.serviceAccountToken`:: +Specifies a {ref}/security-api-create-service-token.html[service account token] for the {es} cluster where your monitoring data is stored when using `monitoring.ui.elasticsearch.hosts`. This setting is an alternative to using `monitoring.ui.elasticsearch.username` and `monitoring.ui.elasticsearch.password`. + `monitoring.ui.elasticsearch.pingTimeout`:: Specifies the time in milliseconds to wait for {es} to respond to internal health checks. By default, it matches the <> setting, From 95ba4f8d93829bca37970b87e18bec9a7b43a062 Mon Sep 17 00:00:00 2001 From: Matthias Wilhelm Date: Tue, 29 Mar 2022 15:54:03 +0200 Subject: [PATCH 21/31] [Discover] Cleanup usage of deprecated APIs (#128713) --- .../actions/explore_data/explore_data_chart_action.test.ts | 3 +-- .../public/actions/explore_data/explore_data_chart_action.ts | 4 ++-- .../actions/explore_data/explore_data_context_menu_action.ts | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts b/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts index b8f44bdbc9a25..f4c6e89280274 100644 --- a/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts +++ b/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.test.ts @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Filter, RangeFilter } from '@kbn/es-query'; import { ExploreDataChartAction } from './explore_data_chart_action'; import { Params, PluginDeps } from './abstract_explore_data_action'; import { coreMock } from '../../../../../../src/core/public/mocks'; @@ -15,7 +15,6 @@ import { VISUALIZE_EMBEDDABLE_TYPE, } from '../../../../../../src/plugins/visualizations/public'; import { ViewMode } from '../../../../../../src/plugins/embeddable/public'; -import { Filter, RangeFilter } from '../../../../../../src/plugins/data/public'; import { DiscoverAppLocator } from '../../../../../../src/plugins/discover/public'; import { sharePluginMock } from '../../../../../../src/plugins/share/public/mocks'; diff --git a/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts b/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts index 4ab9146a06c55..df85390ba0493 100644 --- a/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts +++ b/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_chart_action.ts @@ -12,7 +12,7 @@ import { } from '../../../../../../src/plugins/discover/public'; import { ApplyGlobalFilterActionContext, - esFilters, + extractTimeRange, } from '../../../../../../src/plugins/data/public'; import { IEmbeddable } from '../../../../../../src/plugins/embeddable/public'; import { KibanaLocation } from '../../../../../../src/plugins/share/public'; @@ -55,7 +55,7 @@ export class ExploreDataChartAction } const { embeddable } = context; - const { restOfFilters: filters, timeRange } = esFilters.extractTimeRange( + const { restOfFilters: filters, timeRange } = extractTimeRange( context.filters, context.timeFieldName ); diff --git a/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts b/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts index 3580a3f191e6c..28f41fdb18711 100644 --- a/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts +++ b/x-pack/plugins/discover_enhanced/public/actions/explore_data/explore_data_context_menu_action.ts @@ -4,14 +4,14 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import type { Filter } from '@kbn/es-query'; import { Action } from '../../../../../../src/plugins/ui_actions/public'; import { EmbeddableContext, EmbeddableInput, IEmbeddable, } from '../../../../../../src/plugins/embeddable/public'; -import { Query, Filter, TimeRange } from '../../../../../../src/plugins/data/public'; +import { Query, TimeRange } from '../../../../../../src/plugins/data/public'; import { DiscoverAppLocatorParams } from '../../../../../../src/plugins/discover/public'; import { KibanaLocation } from '../../../../../../src/plugins/share/public'; import * as shared from './shared'; From 3fc2a3940f1afc96ebad2b8bb2ce7545548ec5ae Mon Sep 17 00:00:00 2001 From: Milton Hultgren Date: Tue, 29 Mar 2022 16:29:50 +0200 Subject: [PATCH 22/31] [Infra Monitoring UI] Add docs for Stack Monitoring template versioning (#128762) * [Infra Monitoring UI] Add doc notes for Stack Monitoring template versioning * Add link to reference PR --- x-pack/plugins/monitoring/dev_docs/reference/indices.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/x-pack/plugins/monitoring/dev_docs/reference/indices.md b/x-pack/plugins/monitoring/dev_docs/reference/indices.md index 5f4fd5d498d9a..c1c95d26842a7 100644 --- a/x-pack/plugins/monitoring/dev_docs/reference/indices.md +++ b/x-pack/plugins/monitoring/dev_docs/reference/indices.md @@ -29,6 +29,10 @@ The index templates for `.monitoring-*` are shipped with and managed by Elastics To verify changes to these templates, either make them in place on a running cluster or run elasticsearch from source. +When updating the templates, it is important to increment the version number [here](https://github.com/elastic/elasticsearch/blob/main/x-pack/plugin/monitoring/src/main/java/org/elasticsearch/xpack/monitoring/MonitoringTemplateRegistry.java#L81). Elasticsearch uses this version number to decide if it should re-install the templates. +PRs should add the labels ":Data Management/Monitoring" and "Team:Data Management" to involve the right Elasticsearch members. +[Reference PR](https://github.com/elastic/elasticsearch/pull/85447) + The `metrics-*` and `metricbeat-*` mappings are managed by metricbeat and elastic agent, **code locations TBD**. ## Aliasing From 06fd7e76acef7a4d590cc40bf7ba61bba7cfe213 Mon Sep 17 00:00:00 2001 From: Or Ouziel Date: Tue, 29 Mar 2022 17:32:54 +0300 Subject: [PATCH 23/31] [Cloud Posture] add rules table flyout (#127887) --- .../public/pages/rules/rules_bottom_bar.tsx | 7 +- .../pages/rules/rules_container.test.tsx | 40 ++++- .../public/pages/rules/rules_container.tsx | 3 +- .../public/pages/rules/rules_flyout.tsx | 146 +++++++++++++++++- .../public/pages/rules/rules_table.tsx | 20 +-- .../public/pages/rules/test_subjects.ts | 6 + .../public/pages/rules/translations.ts | 24 +++ 7 files changed, 218 insertions(+), 28 deletions(-) diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_bottom_bar.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_bottom_bar.tsx index ebf4913f895c3..1cd860f74fbbe 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_bottom_bar.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_bottom_bar.tsx @@ -16,7 +16,12 @@ interface RulesBottomBarProps { } export const RulesBottomBar = ({ onSave, onCancel, isLoading }: RulesBottomBarProps) => ( - + diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx index bcbc4d5c4bd44..7782be9c4917e 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.test.tsx @@ -7,7 +7,7 @@ import React from 'react'; import { RulesContainer } from './rules_container'; -import { render, screen, fireEvent } from '@testing-library/react'; +import { render, screen, fireEvent, within } from '@testing-library/react'; import { QueryClient } from 'react-query'; import { useFindCspRules, useBulkUpdateCspRules, type RuleSavedObject } from './use_csp_rules'; import * as TEST_SUBJECTS from './test_subjects'; @@ -38,7 +38,7 @@ const getRuleMock = ({ id = chance.guid(), enabled }: { id?: string; enabled: bo updatedAt: chance.date().toISOString(), attributes: { id, - name: chance.word(), + name: chance.sentence(), enabled, }, } as RuleSavedObject); @@ -336,4 +336,40 @@ describe('', () => { })) ); }); + + it('updates the rules from within the flyout', () => { + const Wrapper = getWrapper(); + const enabled = true; + const rules = Array.from({ length: 20 }, () => getRuleMock({ enabled })); + + (useFindCspRules as jest.Mock).mockReturnValue({ + status: 'success', + data: { + total: rules.length, + savedObjects: rules, + }, + }); + + render( + + + + ); + + const rule = rules[0]; + const rowId = TEST_SUBJECTS.getCspRulesTableRowItemTestId(rule.id); + const switchId = TEST_SUBJECTS.getCspRulesTableItemSwitchTestId(rule.id); + + fireEvent.click(screen.getByTestId(rowId)); // open flyout + + const flyout = screen.getByTestId(TEST_SUBJECTS.CSP_RULES_FLYOUT_CONTAINER); + + fireEvent.click(within(flyout).getByTestId(switchId)); // change to !enabled + fireEvent.click(screen.getByTestId(TEST_SUBJECTS.CSP_RULES_SAVE_BUTTON)); // save + + const { mutate } = useBulkUpdateCspRules(); + + expect(mutate).toHaveBeenCalledTimes(1); + expect(mutate).toHaveBeenCalledWith([{ ...rule.attributes, enabled: !enabled }]); + }); }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx index 9780f9ecd3778..96659337e0c1a 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_container.tsx @@ -214,8 +214,9 @@ export const RulesContainer = () => { )} {selectedRuleId && ( setSelectedRuleId(null)} + toggleRule={toggleRule} /> )} diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx index 8e8e0e37eed0d..54657660c7aa4 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_flyout.tsx @@ -4,23 +4,155 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import React from 'react'; -import { EuiSpacer, EuiFlyout, EuiFlyoutHeader, EuiFlyoutBody } from '@elastic/eui'; +import React, { useState } from 'react'; +import { + EuiSpacer, + EuiFlyout, + type EuiDescriptionListProps, + EuiToolTip, + EuiFlyoutHeader, + EuiFlyoutBody, + EuiTab, + EuiTabs, + EuiTitle, + EuiDescriptionList, + EuiFlexItem, + EuiFlexGroup, + EuiSwitch, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import type { RuleSavedObject } from './use_csp_rules'; +import * as TEXT from './translations'; +import * as TEST_SUBJECTS from './test_subjects'; -interface FindingFlyoutProps { +interface RuleFlyoutProps { onClose(): void; + toggleRule(rule: RuleSavedObject): void; rule: RuleSavedObject; } -export const RuleFlyout = ({ onClose, rule }: FindingFlyoutProps) => { +const tabs = [ + { label: TEXT.OVERVIEW, id: 'overview', disabled: false }, + { label: TEXT.REMEDIATION, id: 'remediation', disabled: false }, + { label: TEXT.REGO_CODE, id: 'rego', disabled: true }, +] as const; + +type RuleTab = typeof tabs[number]['id']; + +const getOverviewCard = (rule: RuleSavedObject): EuiDescriptionListProps['listItems'] => [ + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.frameworkSourcesLabel', { + defaultMessage: 'Framework Sources', + }), + description: '-', // TODO: add value + }, + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.sectionsLabel', { + defaultMessage: 'Sections', + }), + description: '-', // TODO: add value + }, + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.profileApplicabilityLabel', { + defaultMessage: 'Profile Applicability', + }), + description: rule.attributes.description || '', + }, + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.auditLabel', { + defaultMessage: 'Audit', + }), + description: '-', // TODO: add value + }, + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.referencesLabel', { + defaultMessage: 'References', + }), + description: '-', // TODO: add value + }, +]; + +const getRemediationCard = (rule: RuleSavedObject): EuiDescriptionListProps['listItems'] => [ + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.remediationLabel', { + defaultMessage: 'Remediation', + }), + description: rule.attributes.remediation, + }, + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.impactLabel', { + defaultMessage: 'Impact', + }), + description: rule.attributes.impact, + }, + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.defaultValueLabel', { + defaultMessage: 'Default Value', + }), + description: rule.attributes.default_value, + }, + { + title: i18n.translate('xpack.csp.rules.ruleFlyout.rationaleLabel', { + defaultMessage: 'Rationale', + }), + description: rule.attributes.rationale, + }, +]; + +export const RuleFlyout = ({ onClose, rule, toggleRule }: RuleFlyoutProps) => { + const [tab, setTab] = useState('overview'); + return ( - + -

{rule.attributes.name}

+ +

{rule.attributes.name}

+
+ + {tabs.map((item) => ( + setTab(item.id)} + disabled={item.disabled} + > + {item.label} + + ))} +
- + + {tab === 'overview' && toggleRule(rule)} />} + {tab === 'remediation' && ( + + )} +
); }; + +const RuleOverviewTab = ({ rule, toggleRule }: { rule: RuleSavedObject; toggleRule(): void }) => ( + + + + + + + + + + + + +); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx index e8fd704e124f4..c577daebb58a6 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/rules_table.tsx @@ -16,7 +16,6 @@ import { useEuiTheme, } from '@elastic/eui'; import moment from 'moment'; -import { FormattedMessage } from '@kbn/i18n-react'; import type { RulesState } from './rules_container'; import * as TEST_SUBJECTS from './test_subjects'; import * as TEXT from './translations'; @@ -60,7 +59,6 @@ export const RulesTable = ({ pageSize, totalItemCount: total, pageSizeOptions: [1, 5, 10, 25], - showPerPageOptions: true, }; const selection: EuiBasicTableProps['selection'] = { @@ -74,6 +72,7 @@ export const RulesTable = ({ }; const rowProps = (row: RuleSavedObject) => ({ + ['data-test-subj']: TEST_SUBJECTS.getCspRulesTableRowItemTestId(row.id), style: { background: row.id === selectedRuleId ? euiTheme.colors.highlight : undefined }, onClick: (e: MouseEvent) => { const tag = (e.target as HTMLDivElement).tagName; @@ -122,6 +121,7 @@ const getColumns = ({ e.stopPropagation(); setSelectedRuleId(rule.id); }} + data-test-subj={TEST_SUBJECTS.CSP_RULES_TABLE_ROW_ITEM_NAME} > {name} @@ -142,21 +142,7 @@ const getColumns = ({ field: 'attributes.enabled', name: TEXT.ENABLED, render: (enabled, rule) => ( - - ) : ( - - ) - } - > + `${CSP_RULES_TABLE_ITEM_SWITCH}_${id}`; + +export const getCspRulesTableRowItemTestId = (id: string) => + `${CSP_RULES_TABLE_ROW_ITEM_NAME}_${id}`; diff --git a/x-pack/plugins/cloud_security_posture/public/pages/rules/translations.ts b/x-pack/plugins/cloud_security_posture/public/pages/rules/translations.ts index 8523e0afc06c5..a10e4b2efc1fb 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/rules/translations.ts +++ b/x-pack/plugins/cloud_security_posture/public/pages/rules/translations.ts @@ -56,6 +56,18 @@ export const ENABLE = i18n.translate('xpack.csp.rules.enableLabel', { defaultMessage: 'Enable', }); +export const DEACTIVATE = i18n.translate('xpack.csp.rules.deactivateLabel', { + defaultMessage: 'Deactivate', +}); + +export const ACTIVATE = i18n.translate('xpack.csp.rules.activateLabel', { + defaultMessage: 'Activate', +}); + +export const ACTIVATED = i18n.translate('xpack.csp.rules.activatedLabel', { + defaultMessage: 'Activated', +}); + export const MISSING_RULES = i18n.translate('xpack.csp.rules.missingRulesMessage', { defaultMessage: 'Rules are missing', }); @@ -63,3 +75,15 @@ export const MISSING_RULES = i18n.translate('xpack.csp.rules.missingRulesMessage export const UPDATE_FAILED = i18n.translate('xpack.csp.rules.updateFailedMessage', { defaultMessage: 'Update failed', }); + +export const OVERVIEW = i18n.translate('xpack.csp.rules.ruleFlyout.tabs.overviewTabLabel', { + defaultMessage: 'Overview', +}); + +export const REGO_CODE = i18n.translate('xpack.csp.rules.ruleFlyout.tabs.regoCodeTabLabel', { + defaultMessage: 'Rego Code', +}); + +export const REMEDIATION = i18n.translate('xpack.csp.rules.ruleFlyout.tabs.remediationTabLabel', { + defaultMessage: 'Remediation', +}); From 5cf462bad7e0bbc020daadedd53d611534bfc427 Mon Sep 17 00:00:00 2001 From: Madison Caldwell Date: Tue, 29 Mar 2022 10:35:31 -0400 Subject: [PATCH 24/31] Add fixtures generated by kbn-gen-fixtures (#128419) Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../tests/alerts/alerts_compatibility.ts | 416 +- .../security_solution/alerts/7.16.0/data.json | 3590 ++++++++++ .../alerts/7.16.0/mappings.json | 5819 +++++++++++++++++ 3 files changed, 9608 insertions(+), 217 deletions(-) create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json create mode 100644 x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/mappings.json diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts index 889396c2b6125..953dfb42b7b46 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/tests/alerts/alerts_compatibility.ts @@ -46,21 +46,6 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); describe('Alerts Compatibility', function () { - beforeEach(async () => { - await esArchiver.load( - 'x-pack/test/functional/es_archives/security_solution/legacy_cti_signals' - ); - await createSignalsIndex(supertest, log); - }); - - afterEach(async () => { - await esArchiver.unload( - 'x-pack/test/functional/es_archives/security_solution/legacy_cti_signals' - ); - await deleteSignalsIndex(supertest, log); - await deleteAllAlerts(supertest, log); - }); - describe('CTI', () => { const expectedDomain = 'elastic.local'; const expectedProvider = 'provider1'; @@ -72,6 +57,21 @@ export default ({ getService }: FtrProviderContext) => { type: 'indicator_match_rule', }; + beforeEach(async () => { + await esArchiver.load( + 'x-pack/test/functional/es_archives/security_solution/legacy_cti_signals' + ); + await createSignalsIndex(supertest, log); + }); + + afterEach(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/legacy_cti_signals' + ); + await deleteSignalsIndex(supertest, log); + await deleteAllAlerts(supertest, log); + }); + it('allows querying of legacy enriched signals by threat.indicator', async () => { const { body: { @@ -208,6 +208,19 @@ export default ({ getService }: FtrProviderContext) => { }); describe('Query', () => { + beforeEach(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alerts/7.16.0'); + await createSignalsIndex(supertest, log); + }); + + afterEach(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/alerts/7.16.0' + ); + await deleteSignalsIndex(supertest, log); + await deleteAllAlerts(supertest, log); + }); + it('should generate a signal-on-legacy-signal with legacy index pattern', async () => { const rule: QueryCreateSchema = getRuleForSignalTesting([`.siem-signals-*`]); const { id } = await createRule(supertest, log, rule); @@ -236,121 +249,87 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.space_ids': ['default'], 'kibana.alert.rule.tags': [], agent: { - ephemeral_id: '07c24b1e-3663-4372-b982-f2d831e033eb', - hostname: 'elastic.local', - id: 'ce7741d9-3f0a-466d-8ae6-d7d8f883fcec', - name: 'elastic.local', - type: 'auditbeat', - version: '7.14.0', + name: 'security-linux-1.example.dev', + id: 'd8f66724-3cf2-437c-b124-6ac9fb0e2311', + type: 'filebeat', + version: '7.16.0', }, - ecs: { version: '1.10.0' }, - host: { - architecture: 'x86_64', - hostname: 'elastic.local', - id: '1633D595-A115-5BF5-870B-A471B49446C3', - ip: ['192.168.1.1'], - mac: ['aa:bb:cc:dd:ee:ff'], - name: 'elastic.local', - os: { - build: '20G80', - family: 'darwin', - kernel: '20.6.0', - name: 'Mac OS X', - platform: 'darwin', - type: 'macos', - version: '10.16', + log: { + file: { + path: '/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson', }, + offset: 148938, }, - message: 'Process mdworker_shared (PID: 32306) by user elastic STARTED', - process: { - args: [ - '/System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mdworker_shared', - '-s', - 'mdworker', - '-c', - 'MDSImporterWorker', - '-m', - 'com.apple.mdworker.shared', - ], - entity_id: 'wfc7zUuEinqxUbZ6', - executable: - '/System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mdworker_shared', - hash: { sha1: '5f3233fd75c14b315731684d59b632df36a731a6' }, - name: 'mdworker_shared', - pid: 32306, - ppid: 1, - start: '2021-08-04T04:14:48.830Z', - working_directory: '/', + cloud: { + availability_zone: 'us-central1-c', + instance: { + name: 'security-linux-1', + id: '8995531128842994872', + }, + provider: 'gcp', + service: { + name: 'GCE', + }, + machine: { + type: 'g1-small', + }, + project: { + id: 'elastic-siem', + }, + account: { + id: 'elastic-siem', + }, }, - service: { type: 'system' }, - threat: { - indicator: [ - { - domain: 'elastic.local', - event: { - category: 'threat', - created: '2021-08-04T03:53:30.761Z', - dataset: 'ti_abusech.malware', - ingested: '2021-08-04T03:53:37.514040Z', - kind: 'enrichment', - module: 'threatintel', - reference: 'https://urlhaus.abuse.ch/url/12345/', - type: 'indicator', - }, - first_seen: '2021-08-03T20:35:17.000Z', - matched: { - atomic: 'elastic.local', - field: 'host.name', - id: '_tdUD3sBcVT20cvWAkpd', - index: 'filebeat-7.14.0-2021.08.04-000001', - type: 'indicator_match_rule', - }, - provider: 'provider1', - type: 'url', - url: { - domain: 'elastic.local', - extension: 'php', - full: 'http://elastic.local/thing', - original: 'http://elastic.local/thing', - path: '/thing', - scheme: 'http', - }, - }, - ], + ecs: { + version: '7.16.0', + }, + host: { + hostname: 'security-linux-1', + os: { + kernel: '4.19.0-18-cloud-amd64', + codename: 'buster', + name: 'Debian GNU/Linux', + type: 'linux', + family: 'debian', + version: '10 (buster)', + platform: 'debian', + }, + containerized: false, + ip: '11.200.0.194', + name: 'security-linux-1', + architecture: 'x86_64', }, - user: { - effective: { group: { id: '20' }, id: '501' }, - group: { id: '20', name: 'staff' }, - id: '501', - name: 'elastic', - saved: { group: { id: '20' }, id: '501' }, + 'service.name': 'filebeat', + message: 'Status message.', + data_stream: { + namespace: 'default', + type: 'logs', + dataset: 'elastic_agent.filebeat', }, - 'event.action': 'process_started', - 'event.category': ['process'], - 'event.dataset': 'process', + 'event.agent_id_status': 'verified', + 'event.ingested': '2022-03-23T16:50:28.994Z', + 'event.dataset': 'elastic_agent.filebeat', 'event.kind': 'signal', - 'event.module': 'system', - 'event.type': ['start'], 'kibana.alert.ancestors': [ { - depth: 0, - id: 'yNdfD3sBcVT20cvWFEs2', - index: 'auditbeat-7.14.0-2021.08.04-000001', + id: 'Nmyvt38BIyEvspK02HTJ', type: 'event', + index: 'events-index-000001', + depth: 0, }, { - id: '0527411874b23bcea85daf5bf7dcacd144536ba6d92d3230a4a0acfb7de7f512', + id: '5cddda6852c5f8b6c32d4bfa5e876aa51884e0c7a2d4faaababf91ec9cb68de7', type: 'signal', - index: '.siem-signals-default-000001', + index: '.siem-signals-default-000001-7.16.0', depth: 1, - rule: '832f86f0-f4da-11eb-989d-b758d09dbc85', + rule: '5b7cd9a0-aac9-11ec-bb53-fd375b7a173a', }, ], 'kibana.alert.status': 'active', 'kibana.alert.workflow_status': 'open', 'kibana.alert.depth': 2, 'kibana.alert.reason': - 'process event with process mdworker_shared, by elastic on elastic.local created high alert Signal Testing Query.', + 'event on security-linux-1 created high alert Signal Testing Query.', 'kibana.alert.severity': 'high', 'kibana.alert.risk_score': 1, 'kibana.alert.rule.parameters': { @@ -397,13 +376,11 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.rule.version': 1, 'kibana.alert.rule.exceptions_list': [], 'kibana.alert.rule.immutable': false, - 'kibana.alert.original_time': '2021-08-04T04:14:58.973Z', - 'kibana.alert.original_event.action': 'process_started', - 'kibana.alert.original_event.category': ['process'], - 'kibana.alert.original_event.dataset': 'process', + 'kibana.alert.original_time': '2022-03-23T16:50:40.440Z', + 'kibana.alert.original_event.agent_id_status': 'verified', + 'kibana.alert.original_event.ingested': '2022-03-23T16:50:28.994Z', + 'kibana.alert.original_event.dataset': 'elastic_agent.filebeat', 'kibana.alert.original_event.kind': 'signal', - 'kibana.alert.original_event.module': 'system', - 'kibana.alert.original_event.type': ['start'], }); }); @@ -437,121 +414,87 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.space_ids': ['default'], 'kibana.alert.rule.tags': [], agent: { - ephemeral_id: '07c24b1e-3663-4372-b982-f2d831e033eb', - hostname: 'elastic.local', - id: 'ce7741d9-3f0a-466d-8ae6-d7d8f883fcec', - name: 'elastic.local', - type: 'auditbeat', - version: '7.14.0', + name: 'security-linux-1.example.dev', + id: 'd8f66724-3cf2-437c-b124-6ac9fb0e2311', + type: 'filebeat', + version: '7.16.0', }, - ecs: { version: '1.10.0' }, - host: { - architecture: 'x86_64', - hostname: 'elastic.local', - id: '1633D595-A115-5BF5-870B-A471B49446C3', - ip: ['192.168.1.1'], - mac: ['aa:bb:cc:dd:ee:ff'], - name: 'elastic.local', - os: { - build: '20G80', - family: 'darwin', - kernel: '20.6.0', - name: 'Mac OS X', - platform: 'darwin', - type: 'macos', - version: '10.16', + log: { + file: { + path: '/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson', }, + offset: 148938, }, - message: 'Process mdworker_shared (PID: 32306) by user elastic STARTED', - process: { - args: [ - '/System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mdworker_shared', - '-s', - 'mdworker', - '-c', - 'MDSImporterWorker', - '-m', - 'com.apple.mdworker.shared', - ], - entity_id: 'wfc7zUuEinqxUbZ6', - executable: - '/System/Library/Frameworks/CoreServices.framework/Frameworks/Metadata.framework/Versions/A/Support/mdworker_shared', - hash: { sha1: '5f3233fd75c14b315731684d59b632df36a731a6' }, - name: 'mdworker_shared', - pid: 32306, - ppid: 1, - start: '2021-08-04T04:14:48.830Z', - working_directory: '/', + cloud: { + availability_zone: 'us-central1-c', + instance: { + name: 'security-linux-1', + id: '8995531128842994872', + }, + provider: 'gcp', + service: { + name: 'GCE', + }, + machine: { + type: 'g1-small', + }, + project: { + id: 'elastic-siem', + }, + account: { + id: 'elastic-siem', + }, }, - service: { type: 'system' }, - threat: { - indicator: [ - { - domain: 'elastic.local', - event: { - category: 'threat', - created: '2021-08-04T03:53:30.761Z', - dataset: 'ti_abusech.malware', - ingested: '2021-08-04T03:53:37.514040Z', - kind: 'enrichment', - module: 'threatintel', - reference: 'https://urlhaus.abuse.ch/url/12345/', - type: 'indicator', - }, - first_seen: '2021-08-03T20:35:17.000Z', - matched: { - atomic: 'elastic.local', - field: 'host.name', - id: '_tdUD3sBcVT20cvWAkpd', - index: 'filebeat-7.14.0-2021.08.04-000001', - type: 'indicator_match_rule', - }, - provider: 'provider1', - type: 'url', - url: { - domain: 'elastic.local', - extension: 'php', - full: 'http://elastic.local/thing', - original: 'http://elastic.local/thing', - path: '/thing', - scheme: 'http', - }, - }, - ], + ecs: { + version: '7.16.0', + }, + host: { + hostname: 'security-linux-1', + os: { + kernel: '4.19.0-18-cloud-amd64', + codename: 'buster', + name: 'Debian GNU/Linux', + type: 'linux', + family: 'debian', + version: '10 (buster)', + platform: 'debian', + }, + containerized: false, + ip: '11.200.0.194', + name: 'security-linux-1', + architecture: 'x86_64', }, - user: { - effective: { group: { id: '20' }, id: '501' }, - group: { id: '20', name: 'staff' }, - id: '501', - name: 'elastic', - saved: { group: { id: '20' }, id: '501' }, + 'service.name': 'filebeat', + message: 'Status message.', + data_stream: { + namespace: 'default', + type: 'logs', + dataset: 'elastic_agent.filebeat', }, - 'event.action': 'process_started', - 'event.category': ['process'], - 'event.dataset': 'process', + 'event.agent_id_status': 'verified', + 'event.ingested': '2022-03-23T16:50:28.994Z', + 'event.dataset': 'elastic_agent.filebeat', 'event.kind': 'signal', - 'event.module': 'system', - 'event.type': ['start'], 'kibana.alert.ancestors': [ { - depth: 0, - id: 'yNdfD3sBcVT20cvWFEs2', - index: 'auditbeat-7.14.0-2021.08.04-000001', + id: 'Nmyvt38BIyEvspK02HTJ', type: 'event', + index: 'events-index-000001', + depth: 0, }, { - id: '0527411874b23bcea85daf5bf7dcacd144536ba6d92d3230a4a0acfb7de7f512', + id: '5cddda6852c5f8b6c32d4bfa5e876aa51884e0c7a2d4faaababf91ec9cb68de7', type: 'signal', - index: '.siem-signals-default-000001', + index: '.siem-signals-default-000001-7.16.0', depth: 1, - rule: '832f86f0-f4da-11eb-989d-b758d09dbc85', + rule: '5b7cd9a0-aac9-11ec-bb53-fd375b7a173a', }, ], 'kibana.alert.status': 'active', 'kibana.alert.workflow_status': 'open', 'kibana.alert.depth': 2, 'kibana.alert.reason': - 'process event with process mdworker_shared, by elastic on elastic.local created high alert Signal Testing Query.', + 'event on security-linux-1 created high alert Signal Testing Query.', 'kibana.alert.severity': 'high', 'kibana.alert.risk_score': 1, 'kibana.alert.rule.parameters': { @@ -598,18 +541,29 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.rule.version': 1, 'kibana.alert.rule.exceptions_list': [], 'kibana.alert.rule.immutable': false, - 'kibana.alert.original_time': '2021-08-04T04:14:58.973Z', - 'kibana.alert.original_event.action': 'process_started', - 'kibana.alert.original_event.category': ['process'], - 'kibana.alert.original_event.dataset': 'process', + 'kibana.alert.original_time': '2022-03-23T16:50:40.440Z', + 'kibana.alert.original_event.agent_id_status': 'verified', + 'kibana.alert.original_event.ingested': '2022-03-23T16:50:28.994Z', + 'kibana.alert.original_event.dataset': 'elastic_agent.filebeat', 'kibana.alert.original_event.kind': 'signal', - 'kibana.alert.original_event.module': 'system', - 'kibana.alert.original_event.type': ['start'], }); }); }); describe('Saved Query', () => { + beforeEach(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alerts/7.16.0'); + await createSignalsIndex(supertest, log); + }); + + afterEach(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/alerts/7.16.0' + ); + await deleteSignalsIndex(supertest, log); + await deleteAllAlerts(supertest, log); + }); + it('should generate a signal-on-legacy-signal with legacy index pattern', async () => { const rule: SavedQueryCreateSchema = getSavedQueryRuleForSignalTesting([`.siem-signals-*`]); const { id } = await createRule(supertest, log, rule); @@ -636,6 +590,19 @@ export default ({ getService }: FtrProviderContext) => { }); describe('EQL', () => { + beforeEach(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alerts/7.16.0'); + await createSignalsIndex(supertest, log); + }); + + afterEach(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/alerts/7.16.0' + ); + await deleteSignalsIndex(supertest, log); + await deleteAllAlerts(supertest, log); + }); + it('should generate a signal-on-legacy-signal with legacy index pattern', async () => { const rule: EqlCreateSchema = getEqlRuleForSignalTesting(['.siem-signals-*']); const { id } = await createRule(supertest, log, rule); @@ -662,6 +629,19 @@ export default ({ getService }: FtrProviderContext) => { }); describe('Threshold', () => { + beforeEach(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alerts/7.16.0'); + await createSignalsIndex(supertest, log); + }); + + afterEach(async () => { + await esArchiver.unload( + 'x-pack/test/functional/es_archives/security_solution/alerts/7.16.0' + ); + await deleteSignalsIndex(supertest, log); + await deleteAllAlerts(supertest, log); + }); + it('should generate a signal-on-legacy-signal with legacy index pattern', async () => { const baseRule: ThresholdCreateSchema = getThresholdRuleForSignalTesting([ '.siem-signals-*', @@ -670,6 +650,7 @@ export default ({ getService }: FtrProviderContext) => { ...baseRule, threshold: { ...baseRule.threshold, + field: 'host.name', value: 1, }, }; @@ -690,6 +671,7 @@ export default ({ getService }: FtrProviderContext) => { ...baseRule, threshold: { ...baseRule.threshold, + field: 'host.name', value: 1, }, }; diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json b/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json new file mode 100644 index 0000000000000..9f15ea353570e --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/data.json @@ -0,0 +1,3590 @@ +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "0bb0c0d5488d757907f6be6e4c27ff698666948e2cf01d53e8fa43958b36c6a8", + "source": { + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:32.045Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.493Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-1", + "field": "host.name", + "id": "M2yvt38BIyEvspK01XQt", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "P2yvt38BIyEvspK05HSe", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "P2yvt38BIyEvspK05HSe", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-1 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "P2yvt38BIyEvspK05HSe", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:32.045Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:32.045Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "0dd11069ba6c63ec60ac902d6fb0a8a52c4f5ab20f03babe7b861c6d34431bad", + "source": { + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.654Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.495Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-3", + "field": "host.name", + "id": "NWyvt38BIyEvspK013R3", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "Pmyvt38BIyEvspK043Ri", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "Pmyvt38BIyEvspK043Ri", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-3 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "Pmyvt38BIyEvspK043Ri", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:31.654Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.654Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "999fef09ceb58f30dcbbe2a5fd410f8a22dda6179fa5f1041c7a759a31932ef9", + "source": { + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.330Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.496Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-2", + "field": "host.name", + "id": "NGyvt38BIyEvspK01nQn", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "PWyvt38BIyEvspK04XTd", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "PWyvt38BIyEvspK04XTd", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-2 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "PWyvt38BIyEvspK04XTd", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:31.330Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.330Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "f75bc411e6b0c30c26aa310c1e65ff8430cc0a98ddf74c335941dd7456858e85", + "source": { + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.001Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.497Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-1", + "field": "host.name", + "id": "M2yvt38BIyEvspK01XQt", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "PGyvt38BIyEvspK04HSX", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "PGyvt38BIyEvspK04HSX", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-1 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "PGyvt38BIyEvspK04HSX", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:31.001Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.001Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "b46b35ce011486304a3a1e1b1dc2b772e2b80684a3a8663e9cd101691cff7429", + "source": { + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.665Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.498Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-3", + "field": "host.name", + "id": "NWyvt38BIyEvspK013R3", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "O2yvt38BIyEvspK033RN", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "O2yvt38BIyEvspK033RN", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-3 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "O2yvt38BIyEvspK033RN", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:30.665Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.665Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "570caf7637457b9721fd46ec22166adb57916298bf68ef31df07bd0bbac95d7c", + "source": { + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.353Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.499Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-2", + "field": "host.name", + "id": "NGyvt38BIyEvspK01nQn", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "Omyvt38BIyEvspK03nQB", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "Omyvt38BIyEvspK03nQB", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-2 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "Omyvt38BIyEvspK03nQB", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:30.353Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.353Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "0c7bfb7198c9db281b639b1044c74db2b881e3152ee863e6c9304a6fb5d0e5bb", + "source": { + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.031Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.501Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-1", + "field": "host.name", + "id": "M2yvt38BIyEvspK01XQt", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "OWyvt38BIyEvspK03HTF", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "OWyvt38BIyEvspK03HTF", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-1 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "OWyvt38BIyEvspK03HTF", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:30.031Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.031Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "ae1c6e5c7680cdc986ff52b1913e93ba2a010ea207364d4782550adf180e49ee", + "source": { + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:29.715Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.502Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-3", + "field": "host.name", + "id": "NWyvt38BIyEvspK013R3", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "OGyvt38BIyEvspK023SI", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "OGyvt38BIyEvspK023SI", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-3 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "OGyvt38BIyEvspK023SI", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:29.715Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:29.715Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "a73fda6bdb25425c8597f63e2b87b662798ad46f195c47ac4243d9d0b9705dd8", + "source": { + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:29.387Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.503Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-2", + "field": "host.name", + "id": "NGyvt38BIyEvspK01nQn", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "N2yvt38BIyEvspK02nRK", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "N2yvt38BIyEvspK02nRK", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-2 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "N2yvt38BIyEvspK02nRK", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:29.387Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:29.387Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "77038fe81327ce7b578e69896fdd1869fab16d13633b5fb0cb7743bae9120ca5", + "source": { + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:28.994Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:51.504Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "threat": { + "enrichments": [ + { + "indicator": {}, + "matched": { + "atomic": "security-linux-1", + "field": "host.name", + "id": "M2yvt38BIyEvspK01XQt", + "index": "threat-index-000001", + "type": "indicator_match_rule" + } + } + ] + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "Nmyvt38BIyEvspK02HTJ", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "Nmyvt38BIyEvspK02HTJ", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "62f9a8c0-aac9-11ec-aa31-c9ea2cb79db7", + "actions": [], + "interval": "1m", + "name": "threat-match-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:47.264Z", + "updated_at": "2022-03-23T16:50:48.396Z", + "description": "a simple threat match rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "bef9b0da-8c2f-4b82-930f-37ffa1b57fc1", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threat_match", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threat_query": "*", + "threat_mapping": [ + { + "entries": [ + { + "field": "host.name", + "type": "mapping", + "value": "host.name" + } + ] + } + ], + "threat_language": "kuery", + "threat_index": [ + "threat-index-*" + ], + "threat_indicator_path": "threat.indicator" + }, + "reason": "event on security-linux-1 created low alert threat-match-rule.", + "depth": 1, + "parent": { + "id": "Nmyvt38BIyEvspK02HTJ", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:28.994Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:28.994Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "21d26a1ad7b01b28667638d5f8db96f6e94957394efe7a16057948095a445ac4", + "source": { + "@timestamp": "2022-03-23T16:50:48.441Z", + "host.name": "security-linux-1", + "event": { + "kind": "signal" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "8e75aa13-6b35-5d96-b52b-1d62909a9d75", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "8e75aa13-6b35-5d96-b52b-1d62909a9d75", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "60b8b970-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "threshold-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:44.260Z", + "updated_at": "2022-03-23T16:50:45.341Z", + "description": "a simple threshold rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "b97ae2a4-f188-43b2-b082-69667b563152", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threshold", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threshold": { + "field": [ + "host.name" + ], + "value": 1 + } + }, + "reason": "event created low alert threshold-rule.", + "depth": 1, + "parent": { + "id": "8e75aa13-6b35-5d96-b52b-1d62909a9d75", + "type": "event", + "index": "events-index-*", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:32.045Z", + "threshold_result": { + "terms": [ + { + "field": "host.name", + "value": "security-linux-1" + } + ], + "count": 4, + "from": "2022-03-23T06:50:48.395Z" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "4c2a3865ca7df72e4cc17b5114feb2535b2459fd52f6fbd0669d4884f5956dc2", + "source": { + "@timestamp": "2022-03-23T16:50:48.442Z", + "host.name": "security-linux-2", + "event": { + "kind": "signal" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "9c957c24-8ce5-516b-ba8e-44b582da6579", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "9c957c24-8ce5-516b-ba8e-44b582da6579", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "60b8b970-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "threshold-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:44.260Z", + "updated_at": "2022-03-23T16:50:45.341Z", + "description": "a simple threshold rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "b97ae2a4-f188-43b2-b082-69667b563152", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threshold", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threshold": { + "field": [ + "host.name" + ], + "value": 1 + } + }, + "reason": "event created low alert threshold-rule.", + "depth": 1, + "parent": { + "id": "9c957c24-8ce5-516b-ba8e-44b582da6579", + "type": "event", + "index": "events-index-*", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:31.330Z", + "threshold_result": { + "terms": [ + { + "field": "host.name", + "value": "security-linux-2" + } + ], + "count": 3, + "from": "2022-03-23T06:50:48.395Z" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "3754896311b1d9f9dee45ecf06aa5160f8cd3d4504ef5c856ba285edd61d059d", + "source": { + "@timestamp": "2022-03-23T16:50:48.442Z", + "host.name": "security-linux-3", + "event": { + "kind": "signal" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "326cc81c-b55f-5b69-8222-e930bcb24692", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "326cc81c-b55f-5b69-8222-e930bcb24692", + "type": "event", + "index": "events-index-*", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "60b8b970-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "threshold-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:44.260Z", + "updated_at": "2022-03-23T16:50:45.341Z", + "description": "a simple threshold rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "b97ae2a4-f188-43b2-b082-69667b563152", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "threshold", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [], + "threshold": { + "field": [ + "host.name" + ], + "value": 1 + } + }, + "reason": "event created low alert threshold-rule.", + "depth": 1, + "parent": { + "id": "326cc81c-b55f-5b69-8222-e930bcb24692", + "type": "event", + "index": "events-index-*", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:31.654Z", + "threshold_result": { + "terms": [ + { + "field": "host.name", + "value": "security-linux-3" + } + ], + "count": 3, + "from": "2022-03-23T06:50:48.395Z" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "5cddda6852c5f8b6c32d4bfa5e876aa51884e0c7a2d4faaababf91ec9cb68de7", + "source": { + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:28.994Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.440Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "Nmyvt38BIyEvspK02HTJ", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "Nmyvt38BIyEvspK02HTJ", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-1 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "Nmyvt38BIyEvspK02HTJ", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:28.994Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:28.994Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "5050902fa762858249c32b1d228dd71ca9217ace612b65f9669fb3a5f371ab63", + "source": { + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:29.387Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.477Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "N2yvt38BIyEvspK02nRK", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "N2yvt38BIyEvspK02nRK", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-2 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "N2yvt38BIyEvspK02nRK", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:29.387Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:29.387Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "525833fe5aa3cabce849adf9291b4d4009c25edbe528d5d2add1dc749c00513b", + "source": { + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:29.715Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.499Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "OGyvt38BIyEvspK023SI", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "OGyvt38BIyEvspK023SI", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-3 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "OGyvt38BIyEvspK023SI", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:29.715Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:29.715Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "4f9c5a7581544f9dc1fa4c9f541c7e7573d7460ddeeda1875bee081e6615035b", + "source": { + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.031Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.510Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "OWyvt38BIyEvspK03HTF", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "OWyvt38BIyEvspK03HTF", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-1 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "OWyvt38BIyEvspK03HTF", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:30.031Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.031Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "d791d45b87a37e3b8a8388d7d6237728aa14ab6ec81bfa84f96457bd42b39e4a", + "source": { + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.353Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.533Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "Omyvt38BIyEvspK03nQB", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "Omyvt38BIyEvspK03nQB", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-2 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "Omyvt38BIyEvspK03nQB", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:30.353Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.353Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "747a4cfd4dbc1dd3924b341b0d3d94098252579354bf140e1621cb4b8681e911", + "source": { + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.665Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.547Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "O2yvt38BIyEvspK033RN", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "O2yvt38BIyEvspK033RN", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-3 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "O2yvt38BIyEvspK033RN", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:30.665Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:30.665Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "5a217bc36610a820dbbb20f7b189065d631038a9dbb33bde1511f0f6a63183d2", + "source": { + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.001Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.561Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "PGyvt38BIyEvspK04HSX", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "PGyvt38BIyEvspK04HSX", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-1 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "PGyvt38BIyEvspK04HSX", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:31.001Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.001Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "fde1f09c4420ce5747f04ca051bcdc90762394ea019a7cc2cfee8de3bd575a59", + "source": { + "agent": { + "name": "security-linux-2.example.dev", + "id": "87c417dd-08d6-4e24-ad69-285cb8de84e9", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-2", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.195", + "name": "security-linux-2", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.330Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.593Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "PWyvt38BIyEvspK04XTd", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "PWyvt38BIyEvspK04XTd", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-2 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "PWyvt38BIyEvspK04XTd", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:31.330Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.330Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "337f39b1fb862a4c6910605b16e6b5b59623219e99dcb7d442cd334229ad3a7e", + "source": { + "agent": { + "name": "security-linux-3.example.dev", + "id": "06851da1-73e7-41e3-97d6-ff1d62c98dc5", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-3", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.196", + "name": "security-linux-3", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.654Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.606Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "Pmyvt38BIyEvspK043Ri", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "Pmyvt38BIyEvspK043Ri", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-3 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "Pmyvt38BIyEvspK043Ri", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:31.654Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:31.654Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + +{ + "type": "doc", + "value": { + "index": ".siem-signals-default-000001-7.16.0", + "id": "44f8d6e34631ced611f6588e7f0cdf52ac5647eff09cfbd36a38ad2a7d4bf32f", + "source": { + "agent": { + "name": "security-linux-1.example.dev", + "id": "d8f66724-3cf2-437c-b124-6ac9fb0e2311", + "type": "filebeat", + "version": "7.16.0" + }, + "log": { + "file": { + "path": "/opt/Elastic/Agent/data/elastic-agent-a13c93/logs/default/filebeat-20220301-3.ndjson" + }, + "offset": 148938 + }, + "cloud": { + "availability_zone": "us-central1-c", + "instance": { + "name": "security-linux-1", + "id": "8995531128842994872" + }, + "provider": "gcp", + "service": { + "name": "GCE" + }, + "machine": { + "type": "g1-small" + }, + "project": { + "id": "elastic-siem" + }, + "account": { + "id": "elastic-siem" + } + }, + "ecs": { + "version": "7.16.0" + }, + "host": { + "hostname": "security-linux-1", + "os": { + "kernel": "4.19.0-18-cloud-amd64", + "codename": "buster", + "name": "Debian GNU/Linux", + "type": "linux", + "family": "debian", + "version": "10 (buster)", + "platform": "debian" + }, + "containerized": false, + "ip": "11.200.0.194", + "name": "security-linux-1", + "architecture": "x86_64" + }, + "event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:32.045Z", + "dataset": "elastic_agent.filebeat", + "kind": "signal" + }, + "service.name": "filebeat", + "message": "Status message.", + "@timestamp": "2022-03-23T16:50:40.624Z", + "data_stream": { + "namespace": "default", + "type": "logs", + "dataset": "elastic_agent.filebeat" + }, + "signal": { + "_meta": { + "version": 57 + }, + "parents": [ + { + "id": "P2yvt38BIyEvspK05HSe", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "ancestors": [ + { + "id": "P2yvt38BIyEvspK05HSe", + "type": "event", + "index": "events-index-000001", + "depth": 0 + } + ], + "status": "open", + "rule": { + "id": "5b7cd9a0-aac9-11ec-bb53-fd375b7a173a", + "actions": [], + "interval": "1m", + "name": "query-rule", + "tags": [], + "enabled": true, + "created_by": "elastic", + "updated_by": "elastic", + "throttle": null, + "created_at": "2022-03-23T16:50:34.234Z", + "updated_at": "2022-03-23T16:50:36.214Z", + "description": "a simple query rule", + "risk_score": 21, + "severity": "low", + "license": "", + "output_index": ".siem-signals-default-000001", + "author": [], + "false_positives": [], + "from": "now-36000s", + "rule_id": "1fcc46ae-7e1e-4002-a4e1-e456029cb7ec", + "max_signals": 100, + "risk_score_mapping": [], + "severity_mapping": [], + "threat": [], + "to": "now", + "references": [], + "version": 1, + "exceptions_list": [], + "immutable": false, + "type": "query", + "language": "kuery", + "index": [ + "events-index-*" + ], + "query": "*", + "filters": [] + }, + "reason": "event on security-linux-1 created low alert query-rule.", + "depth": 1, + "parent": { + "id": "P2yvt38BIyEvspK05HSe", + "type": "event", + "index": "events-index-000001", + "depth": 0 + }, + "original_time": "2022-03-23T16:50:32.045Z", + "original_event": { + "agent_id_status": "verified", + "ingested": "2022-03-23T16:50:32.045Z", + "dataset": "elastic_agent.filebeat" + } + } + } + } +} + diff --git a/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/mappings.json b/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/mappings.json new file mode 100644 index 0000000000000..3838e29ee5aa4 --- /dev/null +++ b/x-pack/test/functional/es_archives/security_solution/alerts/7.16.0/mappings.json @@ -0,0 +1,5819 @@ +{ + "type": "index", + "value": { + "aliases": { + ".siem-signals-default": { + "is_write_index": true + } + }, + "index": ".siem-signals-default-000001-7.16.0", + "mappings": { + "dynamic": "false", + "_meta": { + "version": 57, + "aliases_version": 1 + }, + "properties": { + "@timestamp": { + "type": "date" + }, + "agent": { + "properties": { + "build": { + "properties": { + "original": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "ephemeral_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + } + } + }, + "client": { + "properties": { + "address": { + "type": "keyword", + "ignore_above": 1024 + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "geo": { + "properties": { + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "postal_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "type": "keyword", + "ignore_above": 1024 + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "subdomain": { + "type": "keyword", + "ignore_above": 1024 + }, + "top_level_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "user": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "cloud": { + "properties": { + "account": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "availability_zone": { + "type": "keyword", + "ignore_above": 1024 + }, + "instance": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "machine": { + "properties": { + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "project": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "provider": { + "type": "keyword", + "ignore_above": 1024 + }, + "region": { + "type": "keyword", + "ignore_above": 1024 + }, + "service": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "status": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "container": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "image": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "tag": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "labels": { + "type": "object" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "runtime": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "data_stream": { + "properties": { + "dataset": { + "type": "keyword" + }, + "namespace": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "destination": { + "properties": { + "address": { + "type": "keyword", + "ignore_above": 1024 + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "geo": { + "properties": { + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "postal_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "type": "keyword", + "ignore_above": 1024 + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "subdomain": { + "type": "keyword", + "ignore_above": 1024 + }, + "top_level_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "user": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "dll": { + "properties": { + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "signing_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "status": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "team_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "hash": { + "properties": { + "md5": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha1": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha256": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha512": { + "type": "keyword", + "ignore_above": 1024 + }, + "ssdeep": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "path": { + "type": "keyword", + "ignore_above": 1024 + }, + "pe": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "company": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "file_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "imphash": { + "type": "keyword", + "ignore_above": 1024 + }, + "original_file_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "product": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "dns": { + "properties": { + "answers": { + "properties": { + "class": { + "type": "keyword", + "ignore_above": 1024 + }, + "data": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "ttl": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "header_flags": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "op_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "question": { + "properties": { + "class": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "registered_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "subdomain": { + "type": "keyword", + "ignore_above": 1024 + }, + "top_level_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "resolved_ip": { + "type": "ip" + }, + "response_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "ecs": { + "properties": { + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "error": { + "properties": { + "code": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "message": { + "type": "text", + "norms": false + }, + "stack_trace": { + "type": "keyword", + "index": false, + "doc_values": false, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "event": { + "properties": { + "action": { + "type": "keyword", + "ignore_above": 1024 + }, + "agent_id_status": { + "type": "keyword", + "ignore_above": 1024 + }, + "category": { + "type": "keyword", + "ignore_above": 1024 + }, + "code": { + "type": "keyword", + "ignore_above": 1024 + }, + "created": { + "type": "date" + }, + "dataset": { + "type": "keyword", + "ignore_above": 1024 + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "ingested": { + "type": "date" + }, + "kind": { + "type": "keyword", + "ignore_above": 1024 + }, + "module": { + "type": "keyword", + "ignore_above": 1024 + }, + "original": { + "type": "keyword", + "index": false, + "doc_values": false + }, + "outcome": { + "type": "keyword", + "ignore_above": 1024 + }, + "provider": { + "type": "keyword", + "ignore_above": 1024 + }, + "reason": { + "type": "keyword", + "ignore_above": 1024 + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "type": "keyword", + "ignore_above": 1024 + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "signing_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "status": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "team_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "type": "keyword", + "ignore_above": 1024 + }, + "directory": { + "type": "keyword", + "ignore_above": 1024 + }, + "drive_letter": { + "type": "keyword", + "ignore_above": 1 + }, + "elf": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "byte_order": { + "type": "keyword", + "ignore_above": 1024 + }, + "cpu_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "class": { + "type": "keyword", + "ignore_above": 1024 + }, + "data": { + "type": "keyword", + "ignore_above": 1024 + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_abi": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "type": "nested", + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "physical_offset": { + "type": "keyword", + "ignore_above": 1024 + }, + "physical_size": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + } + }, + "segments": { + "type": "nested", + "properties": { + "sections": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "shared_libraries": { + "type": "keyword", + "ignore_above": 1024 + }, + "telfhash": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "extension": { + "type": "keyword", + "ignore_above": 1024 + }, + "gid": { + "type": "keyword", + "ignore_above": 1024 + }, + "group": { + "type": "keyword", + "ignore_above": 1024 + }, + "hash": { + "properties": { + "md5": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha1": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha256": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha512": { + "type": "keyword", + "ignore_above": 1024 + }, + "ssdeep": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "inode": { + "type": "keyword", + "ignore_above": 1024 + }, + "mime_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "mode": { + "type": "keyword", + "ignore_above": 1024 + }, + "mtime": { + "type": "date" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "owner": { + "type": "keyword", + "ignore_above": 1024 + }, + "path": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "pe": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "company": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "file_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "imphash": { + "type": "keyword", + "ignore_above": 1024 + }, + "original_file_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "product": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "uid": { + "type": "keyword", + "ignore_above": 1024 + }, + "x509": { + "properties": { + "alternative_names": { + "type": "keyword", + "ignore_above": 1024 + }, + "issuer": { + "properties": { + "common_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country": { + "type": "keyword", + "ignore_above": 1024 + }, + "distinguished_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "locality": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "organizational_unit": { + "type": "keyword", + "ignore_above": 1024 + }, + "state_or_province": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "type": "keyword", + "ignore_above": 1024 + }, + "public_key_curve": { + "type": "keyword", + "ignore_above": 1024 + }, + "public_key_exponent": { + "type": "long", + "index": false, + "doc_values": false + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "type": "keyword", + "ignore_above": 1024 + }, + "signature_algorithm": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject": { + "properties": { + "common_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country": { + "type": "keyword", + "ignore_above": 1024 + }, + "distinguished_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "locality": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "organizational_unit": { + "type": "keyword", + "ignore_above": 1024 + }, + "state_or_province": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "version_number": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "geo": { + "properties": { + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "properties": { + "md5": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha1": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha256": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha512": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "host": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "cpu": { + "properties": { + "usage": { + "type": "scaled_float", + "scaling_factor": 1000 + } + } + }, + "disk": { + "properties": { + "read": { + "properties": { + "bytes": { + "type": "long" + } + } + }, + "write": { + "properties": { + "bytes": { + "type": "long" + } + } + } + } + }, + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "geo": { + "properties": { + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "postal_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "ip": { + "type": "ip" + }, + "mac": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "network": { + "properties": { + "egress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + }, + "ingress": { + "properties": { + "bytes": { + "type": "long" + }, + "packets": { + "type": "long" + } + } + } + } + }, + "os": { + "properties": { + "family": { + "type": "keyword", + "ignore_above": 1024 + }, + "full": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "kernel": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "caseless": { + "type": "keyword", + "ignore_above": 1024, + "normalizer": "lowercase" + }, + "text": { + "type": "text", + "norms": false + } + } + }, + "platform": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "uptime": { + "type": "long" + }, + "user": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "http": { + "properties": { + "request": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "method": { + "type": "keyword", + "ignore_above": 1024 + }, + "mime_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "referrer": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "response": { + "properties": { + "body": { + "properties": { + "bytes": { + "type": "long" + }, + "content": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "mime_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "status_code": { + "type": "long" + } + } + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "interface": { + "properties": { + "alias": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "kibana": { + "properties": { + "alert": { + "properties": { + "ancestors": { + "properties": { + "depth": { + "type": "alias", + "path": "signal.ancestors.depth" + }, + "id": { + "type": "alias", + "path": "signal.ancestors.id" + }, + "index": { + "type": "alias", + "path": "signal.ancestors.index" + }, + "type": { + "type": "alias", + "path": "signal.ancestors.type" + } + } + }, + "depth": { + "type": "alias", + "path": "signal.depth" + }, + "original_event": { + "properties": { + "action": { + "type": "alias", + "path": "signal.original_event.action" + }, + "category": { + "type": "alias", + "path": "signal.original_event.category" + }, + "code": { + "type": "alias", + "path": "signal.original_event.code" + }, + "created": { + "type": "alias", + "path": "signal.original_event.created" + }, + "dataset": { + "type": "alias", + "path": "signal.original_event.dataset" + }, + "duration": { + "type": "alias", + "path": "signal.original_event.duration" + }, + "end": { + "type": "alias", + "path": "signal.original_event.end" + }, + "hash": { + "type": "alias", + "path": "signal.original_event.hash" + }, + "id": { + "type": "alias", + "path": "signal.original_event.id" + }, + "kind": { + "type": "alias", + "path": "signal.original_event.kind" + }, + "module": { + "type": "alias", + "path": "signal.original_event.module" + }, + "outcome": { + "type": "alias", + "path": "signal.original_event.outcome" + }, + "provider": { + "type": "alias", + "path": "signal.original_event.provider" + }, + "reason": { + "type": "alias", + "path": "signal.original_event.reason" + }, + "risk_score": { + "type": "alias", + "path": "signal.original_event.risk_score" + }, + "risk_score_norm": { + "type": "alias", + "path": "signal.original_event.risk_score_norm" + }, + "sequence": { + "type": "alias", + "path": "signal.original_event.sequence" + }, + "severity": { + "type": "alias", + "path": "signal.original_event.severity" + }, + "start": { + "type": "alias", + "path": "signal.original_event.start" + }, + "timezone": { + "type": "alias", + "path": "signal.original_event.timezone" + }, + "type": { + "type": "alias", + "path": "signal.original_event.type" + } + } + }, + "original_time": { + "type": "alias", + "path": "signal.original_time" + }, + "reason": { + "type": "alias", + "path": "signal.reason" + }, + "risk_score": { + "type": "alias", + "path": "signal.rule.risk_score" + }, + "rule": { + "properties": { + "author": { + "type": "alias", + "path": "signal.rule.author" + }, + "building_block_type": { + "type": "alias", + "path": "signal.rule.building_block_type" + }, + "created_at": { + "type": "alias", + "path": "signal.rule.created_at" + }, + "created_by": { + "type": "alias", + "path": "signal.rule.created_by" + }, + "description": { + "type": "alias", + "path": "signal.rule.description" + }, + "enabled": { + "type": "alias", + "path": "signal.rule.enabled" + }, + "false_positives": { + "type": "alias", + "path": "signal.rule.false_positives" + }, + "from": { + "type": "alias", + "path": "signal.rule.from" + }, + "immutable": { + "type": "alias", + "path": "signal.rule.immutable" + }, + "index": { + "type": "alias", + "path": "signal.rule.index" + }, + "interval": { + "type": "alias", + "path": "signal.rule.interval" + }, + "language": { + "type": "alias", + "path": "signal.rule.language" + }, + "license": { + "type": "alias", + "path": "signal.rule.license" + }, + "max_signals": { + "type": "alias", + "path": "signal.rule.max_signals" + }, + "name": { + "type": "alias", + "path": "signal.rule.name" + }, + "note": { + "type": "alias", + "path": "signal.rule.note" + }, + "query": { + "type": "alias", + "path": "signal.rule.query" + }, + "references": { + "type": "alias", + "path": "signal.rule.references" + }, + "risk_score_mapping": { + "properties": { + "field": { + "type": "alias", + "path": "signal.rule.risk_score_mapping.field" + }, + "operator": { + "type": "alias", + "path": "signal.rule.risk_score_mapping.operator" + }, + "value": { + "type": "alias", + "path": "signal.rule.risk_score_mapping.value" + } + } + }, + "rule_id": { + "type": "alias", + "path": "signal.rule.rule_id" + }, + "rule_name_override": { + "type": "alias", + "path": "signal.rule.rule_name_override" + }, + "saved_id": { + "type": "alias", + "path": "signal.rule.saved_id" + }, + "severity_mapping": { + "properties": { + "field": { + "type": "alias", + "path": "signal.rule.severity_mapping.field" + }, + "operator": { + "type": "alias", + "path": "signal.rule.severity_mapping.operator" + }, + "severity": { + "type": "alias", + "path": "signal.rule.severity_mapping.severity" + }, + "value": { + "type": "alias", + "path": "signal.rule.severity_mapping.value" + } + } + }, + "tags": { + "type": "alias", + "path": "signal.rule.tags" + }, + "threat": { + "properties": { + "framework": { + "type": "alias", + "path": "signal.rule.threat.framework" + }, + "tactic": { + "properties": { + "id": { + "type": "alias", + "path": "signal.rule.threat.tactic.id" + }, + "name": { + "type": "alias", + "path": "signal.rule.threat.tactic.name" + }, + "reference": { + "type": "alias", + "path": "signal.rule.threat.tactic.reference" + } + } + }, + "technique": { + "properties": { + "id": { + "type": "alias", + "path": "signal.rule.threat.technique.id" + }, + "name": { + "type": "alias", + "path": "signal.rule.threat.technique.name" + }, + "reference": { + "type": "alias", + "path": "signal.rule.threat.technique.reference" + }, + "subtechnique": { + "properties": { + "id": { + "type": "alias", + "path": "signal.rule.threat.technique.subtechnique.id" + }, + "name": { + "type": "alias", + "path": "signal.rule.threat.technique.subtechnique.name" + }, + "reference": { + "type": "alias", + "path": "signal.rule.threat.technique.subtechnique.reference" + } + } + } + } + } + } + }, + "threat_index": { + "type": "alias", + "path": "signal.rule.threat_index" + }, + "threat_indicator_path": { + "type": "alias", + "path": "signal.rule.threat_indicator_path" + }, + "threat_language": { + "type": "alias", + "path": "signal.rule.threat_language" + }, + "threat_mapping": { + "properties": { + "entries": { + "properties": { + "field": { + "type": "alias", + "path": "signal.rule.threat_mapping.entries.field" + }, + "type": { + "type": "alias", + "path": "signal.rule.threat_mapping.entries.type" + }, + "value": { + "type": "alias", + "path": "signal.rule.threat_mapping.entries.value" + } + } + } + } + }, + "threat_query": { + "type": "alias", + "path": "signal.rule.threat_query" + }, + "threshold": { + "properties": { + "field": { + "type": "alias", + "path": "signal.rule.threshold.field" + }, + "value": { + "type": "alias", + "path": "signal.rule.threshold.value" + } + } + }, + "timeline_id": { + "type": "alias", + "path": "signal.rule.timeline_id" + }, + "timeline_title": { + "type": "alias", + "path": "signal.rule.timeline_title" + }, + "to": { + "type": "alias", + "path": "signal.rule.to" + }, + "type": { + "type": "alias", + "path": "signal.rule.type" + }, + "updated_at": { + "type": "alias", + "path": "signal.rule.updated_at" + }, + "updated_by": { + "type": "alias", + "path": "signal.rule.updated_by" + }, + "uuid": { + "type": "alias", + "path": "signal.rule.id" + }, + "version": { + "type": "alias", + "path": "signal.rule.version" + } + } + }, + "severity": { + "type": "alias", + "path": "signal.rule.severity" + }, + "threshold_result": { + "properties": { + "cardinality": { + "properties": { + "field": { + "type": "alias", + "path": "signal.threshold_result.cardinality.field" + }, + "value": { + "type": "alias", + "path": "signal.threshold_result.cardinality.value" + } + } + }, + "count": { + "type": "alias", + "path": "signal.threshold_result.count" + }, + "from": { + "type": "alias", + "path": "signal.threshold_result.from" + }, + "terms": { + "properties": { + "field": { + "type": "alias", + "path": "signal.threshold_result.terms.field" + }, + "value": { + "type": "alias", + "path": "signal.threshold_result.terms.value" + } + } + } + } + }, + "workflow_status": { + "type": "alias", + "path": "signal.status" + } + } + } + } + }, + "labels": { + "type": "object" + }, + "log": { + "properties": { + "file": { + "properties": { + "path": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "level": { + "type": "keyword", + "ignore_above": 1024 + }, + "logger": { + "type": "keyword", + "ignore_above": 1024 + }, + "origin": { + "properties": { + "file": { + "properties": { + "line": { + "type": "integer" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "function": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "original": { + "type": "keyword", + "index": false, + "doc_values": false + }, + "syslog": { + "properties": { + "facility": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "priority": { + "type": "long" + }, + "severity": { + "properties": { + "code": { + "type": "long" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "message": { + "type": "text", + "norms": false + }, + "network": { + "properties": { + "application": { + "type": "keyword", + "ignore_above": 1024 + }, + "bytes": { + "type": "long" + }, + "community_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "direction": { + "type": "keyword", + "ignore_above": 1024 + }, + "forwarded_ip": { + "type": "ip" + }, + "iana_number": { + "type": "keyword", + "ignore_above": 1024 + }, + "inner": { + "properties": { + "vlan": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "packets": { + "type": "long" + }, + "protocol": { + "type": "keyword", + "ignore_above": 1024 + }, + "transport": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "vlan": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "observer": { + "properties": { + "egress": { + "properties": { + "interface": { + "properties": { + "alias": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "vlan": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "zone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "geo": { + "properties": { + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "postal_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hostname": { + "type": "keyword", + "ignore_above": 1024 + }, + "ingress": { + "properties": { + "interface": { + "properties": { + "alias": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "vlan": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "zone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "os": { + "properties": { + "family": { + "type": "keyword", + "ignore_above": 1024 + }, + "full": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "kernel": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "platform": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "product": { + "type": "keyword", + "ignore_above": 1024 + }, + "serial_number": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "vendor": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "orchestrator": { + "properties": { + "api_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "cluster": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "namespace": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "resource": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "organization": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + }, + "os": { + "properties": { + "family": { + "type": "keyword", + "ignore_above": 1024 + }, + "full": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "kernel": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "platform": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "package": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "build_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "checksum": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "install_scope": { + "type": "keyword", + "ignore_above": 1024 + }, + "installed": { + "type": "date" + }, + "license": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "path": { + "type": "keyword", + "ignore_above": 1024 + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + }, + "size": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "pe": { + "properties": { + "company": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "file_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "original_file_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "product": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "process": { + "properties": { + "args": { + "type": "keyword", + "ignore_above": 1024 + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "signing_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "status": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "team_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "elf": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "byte_order": { + "type": "keyword", + "ignore_above": 1024 + }, + "cpu_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "class": { + "type": "keyword", + "ignore_above": 1024 + }, + "data": { + "type": "keyword", + "ignore_above": 1024 + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_abi": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "type": "nested", + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "physical_offset": { + "type": "keyword", + "ignore_above": 1024 + }, + "physical_size": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + } + }, + "segments": { + "type": "nested", + "properties": { + "sections": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "shared_libraries": { + "type": "keyword", + "ignore_above": 1024 + }, + "telfhash": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "entity_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "executable": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "exit_code": { + "type": "long" + }, + "hash": { + "properties": { + "md5": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha1": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha256": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha512": { + "type": "keyword", + "ignore_above": 1024 + }, + "ssdeep": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "parent": { + "properties": { + "args": { + "type": "keyword", + "ignore_above": 1024 + }, + "args_count": { + "type": "long" + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "signing_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "status": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "team_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "command_line": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "elf": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "byte_order": { + "type": "keyword", + "ignore_above": 1024 + }, + "cpu_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "class": { + "type": "keyword", + "ignore_above": 1024 + }, + "data": { + "type": "keyword", + "ignore_above": 1024 + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_abi": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "type": "nested", + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "physical_offset": { + "type": "keyword", + "ignore_above": 1024 + }, + "physical_size": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + } + }, + "segments": { + "type": "nested", + "properties": { + "sections": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "shared_libraries": { + "type": "keyword", + "ignore_above": 1024 + }, + "telfhash": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "entity_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "executable": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "exit_code": { + "type": "long" + }, + "hash": { + "properties": { + "md5": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha1": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha256": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha512": { + "type": "keyword", + "ignore_above": 1024 + }, + "ssdeep": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "pe": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "company": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "file_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "imphash": { + "type": "keyword", + "ignore_above": 1024 + }, + "original_file_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "product": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "thread": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "title": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "uptime": { + "type": "long" + }, + "working_directory": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + }, + "pe": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "company": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "file_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "imphash": { + "type": "keyword", + "ignore_above": 1024 + }, + "original_file_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "product": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "pgid": { + "type": "long" + }, + "pid": { + "type": "long" + }, + "ppid": { + "type": "long" + }, + "start": { + "type": "date" + }, + "thread": { + "properties": { + "id": { + "type": "long" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "title": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "uptime": { + "type": "long" + }, + "working_directory": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "type": "keyword", + "ignore_above": 1024 + }, + "strings": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hive": { + "type": "keyword", + "ignore_above": 1024 + }, + "key": { + "type": "keyword", + "ignore_above": 1024 + }, + "path": { + "type": "keyword", + "ignore_above": 1024 + }, + "value": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "related": { + "properties": { + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "hosts": { + "type": "keyword", + "ignore_above": 1024 + }, + "ip": { + "type": "ip" + }, + "user": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "rule": { + "properties": { + "author": { + "type": "keyword", + "ignore_above": 1024 + }, + "category": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "license": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + }, + "ruleset": { + "type": "keyword", + "ignore_above": 1024 + }, + "uuid": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "server": { + "properties": { + "address": { + "type": "keyword", + "ignore_above": 1024 + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "geo": { + "properties": { + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "postal_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "type": "keyword", + "ignore_above": 1024 + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "subdomain": { + "type": "keyword", + "ignore_above": 1024 + }, + "top_level_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "user": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "service": { + "properties": { + "ephemeral_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "node": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "state": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "signal": { + "properties": { + "_meta": { + "properties": { + "version": { + "type": "long" + } + } + }, + "ancestors": { + "properties": { + "depth": { + "type": "long" + }, + "id": { + "type": "keyword" + }, + "index": { + "type": "keyword" + }, + "rule": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "depth": { + "type": "integer" + }, + "group": { + "properties": { + "id": { + "type": "keyword" + }, + "index": { + "type": "integer" + } + } + }, + "original_event": { + "properties": { + "action": { + "type": "keyword" + }, + "category": { + "type": "keyword" + }, + "code": { + "type": "keyword" + }, + "created": { + "type": "date" + }, + "dataset": { + "type": "keyword" + }, + "duration": { + "type": "long" + }, + "end": { + "type": "date" + }, + "hash": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "kind": { + "type": "keyword" + }, + "module": { + "type": "keyword" + }, + "original": { + "type": "keyword", + "index": false, + "doc_values": false + }, + "outcome": { + "type": "keyword" + }, + "provider": { + "type": "keyword" + }, + "reason": { + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_norm": { + "type": "float" + }, + "sequence": { + "type": "long" + }, + "severity": { + "type": "long" + }, + "start": { + "type": "date" + }, + "timezone": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "original_signal": { + "type": "object", + "dynamic": "false", + "enabled": false + }, + "original_time": { + "type": "date" + }, + "parent": { + "properties": { + "depth": { + "type": "long" + }, + "id": { + "type": "keyword" + }, + "index": { + "type": "keyword" + }, + "rule": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "parents": { + "properties": { + "depth": { + "type": "long" + }, + "id": { + "type": "keyword" + }, + "index": { + "type": "keyword" + }, + "rule": { + "type": "keyword" + }, + "type": { + "type": "keyword" + } + } + }, + "reason": { + "type": "keyword" + }, + "rule": { + "properties": { + "author": { + "type": "keyword" + }, + "building_block_type": { + "type": "keyword" + }, + "created_at": { + "type": "date" + }, + "created_by": { + "type": "keyword" + }, + "description": { + "type": "keyword" + }, + "enabled": { + "type": "keyword" + }, + "false_positives": { + "type": "keyword" + }, + "filters": { + "type": "object" + }, + "from": { + "type": "keyword" + }, + "id": { + "type": "keyword" + }, + "immutable": { + "type": "keyword" + }, + "index": { + "type": "keyword" + }, + "interval": { + "type": "keyword" + }, + "language": { + "type": "keyword" + }, + "license": { + "type": "keyword" + }, + "max_signals": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "note": { + "type": "text" + }, + "output_index": { + "type": "keyword" + }, + "query": { + "type": "keyword" + }, + "references": { + "type": "keyword" + }, + "risk_score": { + "type": "float" + }, + "risk_score_mapping": { + "properties": { + "field": { + "type": "keyword" + }, + "operator": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "rule_id": { + "type": "keyword" + }, + "rule_name_override": { + "type": "keyword" + }, + "saved_id": { + "type": "keyword" + }, + "severity": { + "type": "keyword" + }, + "severity_mapping": { + "properties": { + "field": { + "type": "keyword" + }, + "operator": { + "type": "keyword" + }, + "severity": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + }, + "size": { + "type": "keyword" + }, + "tags": { + "type": "keyword" + }, + "threat": { + "properties": { + "framework": { + "type": "keyword" + }, + "tactic": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + } + } + }, + "technique": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + }, + "subtechnique": { + "properties": { + "id": { + "type": "keyword" + }, + "name": { + "type": "keyword" + }, + "reference": { + "type": "keyword" + } + } + } + } + } + } + }, + "threat_filters": { + "type": "object" + }, + "threat_index": { + "type": "keyword" + }, + "threat_indicator_path": { + "type": "keyword" + }, + "threat_language": { + "type": "keyword" + }, + "threat_mapping": { + "properties": { + "entries": { + "properties": { + "field": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + }, + "threat_query": { + "type": "keyword" + }, + "threshold": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "float" + } + } + }, + "timeline_id": { + "type": "keyword" + }, + "timeline_title": { + "type": "keyword" + }, + "timestamp_override": { + "type": "keyword" + }, + "to": { + "type": "keyword" + }, + "type": { + "type": "keyword" + }, + "updated_at": { + "type": "date" + }, + "updated_by": { + "type": "keyword" + }, + "version": { + "type": "keyword" + } + } + }, + "status": { + "type": "keyword" + }, + "threshold_count": { + "type": "float" + }, + "threshold_result": { + "properties": { + "cardinality": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "long" + } + } + }, + "count": { + "type": "long" + }, + "from": { + "type": "date" + }, + "terms": { + "properties": { + "field": { + "type": "keyword" + }, + "value": { + "type": "keyword" + } + } + } + } + } + } + }, + "source": { + "properties": { + "address": { + "type": "keyword", + "ignore_above": 1024 + }, + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + } + } + }, + "bytes": { + "type": "long" + }, + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "geo": { + "properties": { + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "postal_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "ip": { + "type": "ip" + }, + "mac": { + "type": "keyword", + "ignore_above": 1024 + }, + "nat": { + "properties": { + "ip": { + "type": "ip" + }, + "port": { + "type": "long" + } + } + }, + "packets": { + "type": "long" + }, + "port": { + "type": "long" + }, + "registered_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "subdomain": { + "type": "keyword", + "ignore_above": 1024 + }, + "top_level_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "user": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "span": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "tags": { + "type": "keyword", + "ignore_above": 1024 + }, + "threat": { + "properties": { + "enrichments": { + "type": "nested", + "properties": { + "indicator": { + "properties": { + "as": { + "properties": { + "number": { + "type": "long" + }, + "organization": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + } + } + } + } + }, + "confidence": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "properties": { + "address": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "file": { + "properties": { + "accessed": { + "type": "date" + }, + "attributes": { + "type": "keyword", + "ignore_above": 1024 + }, + "code_signature": { + "properties": { + "exists": { + "type": "boolean" + }, + "signing_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "status": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "team_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "trusted": { + "type": "boolean" + }, + "valid": { + "type": "boolean" + } + } + }, + "created": { + "type": "date" + }, + "ctime": { + "type": "date" + }, + "device": { + "type": "keyword", + "ignore_above": 1024 + }, + "directory": { + "type": "keyword", + "ignore_above": 1024 + }, + "drive_letter": { + "type": "keyword", + "ignore_above": 1 + }, + "elf": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "byte_order": { + "type": "keyword", + "ignore_above": 1024 + }, + "cpu_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "creation_date": { + "type": "date" + }, + "exports": { + "type": "flattened" + }, + "header": { + "properties": { + "abi_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "class": { + "type": "keyword", + "ignore_above": 1024 + }, + "data": { + "type": "keyword", + "ignore_above": 1024 + }, + "entrypoint": { + "type": "long" + }, + "object_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "os_abi": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "imports": { + "type": "flattened" + }, + "sections": { + "type": "nested", + "properties": { + "chi2": { + "type": "long" + }, + "entropy": { + "type": "long" + }, + "flags": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "physical_offset": { + "type": "keyword", + "ignore_above": 1024 + }, + "physical_size": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "virtual_address": { + "type": "long" + }, + "virtual_size": { + "type": "long" + } + } + }, + "segments": { + "type": "nested", + "properties": { + "sections": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "shared_libraries": { + "type": "keyword", + "ignore_above": 1024 + }, + "telfhash": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "extension": { + "type": "keyword", + "ignore_above": 1024 + }, + "gid": { + "type": "keyword", + "ignore_above": 1024 + }, + "group": { + "type": "keyword", + "ignore_above": 1024 + }, + "inode": { + "type": "keyword", + "ignore_above": 1024 + }, + "mime_type": { + "type": "keyword", + "ignore_above": 1024 + }, + "mode": { + "type": "keyword", + "ignore_above": 1024 + }, + "mtime": { + "type": "date" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "owner": { + "type": "keyword", + "ignore_above": 1024 + }, + "path": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "size": { + "type": "long" + }, + "target_path": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "uid": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "first_seen": { + "type": "date" + }, + "geo": { + "properties": { + "city_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "continent_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "country_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "location": { + "type": "geo_point" + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "postal_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_iso_code": { + "type": "keyword", + "ignore_above": 1024 + }, + "region_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "timezone": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "properties": { + "md5": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha1": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha256": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha512": { + "type": "keyword", + "ignore_above": 1024 + }, + "ssdeep": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "ip": { + "type": "ip" + }, + "last_seen": { + "type": "date" + }, + "marking": { + "properties": { + "tlp": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "modified_at": { + "type": "date" + }, + "pe": { + "properties": { + "architecture": { + "type": "keyword", + "ignore_above": 1024 + }, + "company": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024 + }, + "file_version": { + "type": "keyword", + "ignore_above": 1024 + }, + "imphash": { + "type": "keyword", + "ignore_above": 1024 + }, + "original_file_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "product": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "port": { + "type": "long" + }, + "provider": { + "type": "keyword", + "ignore_above": 1024 + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + }, + "registry": { + "properties": { + "data": { + "properties": { + "bytes": { + "type": "keyword", + "ignore_above": 1024 + }, + "strings": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hive": { + "type": "keyword", + "ignore_above": 1024 + }, + "key": { + "type": "keyword", + "ignore_above": 1024 + }, + "path": { + "type": "keyword", + "ignore_above": 1024 + }, + "value": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "scanner_stats": { + "type": "long" + }, + "sightings": { + "type": "long" + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "url": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "extension": { + "type": "keyword", + "ignore_above": 1024 + }, + "fragment": { + "type": "keyword", + "ignore_above": 1024 + }, + "full": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "original": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "password": { + "type": "keyword", + "ignore_above": 1024 + }, + "path": { + "type": "keyword", + "ignore_above": 1024 + }, + "port": { + "type": "long" + }, + "query": { + "type": "keyword", + "ignore_above": 1024 + }, + "registered_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "scheme": { + "type": "keyword", + "ignore_above": 1024 + }, + "subdomain": { + "type": "keyword", + "ignore_above": 1024 + }, + "top_level_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "username": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "x509": { + "properties": { + "alternative_names": { + "type": "keyword", + "ignore_above": 1024 + }, + "issuer": { + "properties": { + "common_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country": { + "type": "keyword", + "ignore_above": 1024 + }, + "distinguished_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "locality": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "organizational_unit": { + "type": "keyword", + "ignore_above": 1024 + }, + "state_or_province": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "type": "keyword", + "ignore_above": 1024 + }, + "public_key_curve": { + "type": "keyword", + "ignore_above": 1024 + }, + "public_key_exponent": { + "type": "long", + "index": false, + "doc_values": false + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "type": "keyword", + "ignore_above": 1024 + }, + "signature_algorithm": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject": { + "properties": { + "common_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country": { + "type": "keyword", + "ignore_above": 1024 + }, + "distinguished_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "locality": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "organizational_unit": { + "type": "keyword", + "ignore_above": 1024 + }, + "state_or_province": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "version_number": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "matched": { + "properties": { + "atomic": { + "type": "keyword", + "ignore_above": 1024 + }, + "field": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "index": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "framework": { + "type": "keyword", + "ignore_above": 1024 + }, + "group": { + "properties": { + "alias": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "software": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "platforms": { + "type": "keyword", + "ignore_above": 1024 + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "tactic": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "technique": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + }, + "subtechnique": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + } + } + }, + "tls": { + "properties": { + "cipher": { + "type": "keyword", + "ignore_above": 1024 + }, + "client": { + "properties": { + "certificate": { + "type": "keyword", + "ignore_above": 1024 + }, + "certificate_chain": { + "type": "keyword", + "ignore_above": 1024 + }, + "hash": { + "properties": { + "md5": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha1": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha256": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "issuer": { + "type": "keyword", + "ignore_above": 1024 + }, + "ja3": { + "type": "keyword", + "ignore_above": 1024 + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "server_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject": { + "type": "keyword", + "ignore_above": 1024 + }, + "supported_ciphers": { + "type": "keyword", + "ignore_above": 1024 + }, + "x509": { + "properties": { + "alternative_names": { + "type": "keyword", + "ignore_above": 1024 + }, + "issuer": { + "properties": { + "common_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country": { + "type": "keyword", + "ignore_above": 1024 + }, + "distinguished_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "locality": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "organizational_unit": { + "type": "keyword", + "ignore_above": 1024 + }, + "state_or_province": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "type": "keyword", + "ignore_above": 1024 + }, + "public_key_curve": { + "type": "keyword", + "ignore_above": 1024 + }, + "public_key_exponent": { + "type": "long", + "index": false, + "doc_values": false + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "type": "keyword", + "ignore_above": 1024 + }, + "signature_algorithm": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject": { + "properties": { + "common_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country": { + "type": "keyword", + "ignore_above": 1024 + }, + "distinguished_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "locality": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "organizational_unit": { + "type": "keyword", + "ignore_above": 1024 + }, + "state_or_province": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "version_number": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "curve": { + "type": "keyword", + "ignore_above": 1024 + }, + "established": { + "type": "boolean" + }, + "next_protocol": { + "type": "keyword", + "ignore_above": 1024 + }, + "resumed": { + "type": "boolean" + }, + "server": { + "properties": { + "certificate": { + "type": "keyword", + "ignore_above": 1024 + }, + "certificate_chain": { + "type": "keyword", + "ignore_above": 1024 + }, + "hash": { + "properties": { + "md5": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha1": { + "type": "keyword", + "ignore_above": 1024 + }, + "sha256": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "issuer": { + "type": "keyword", + "ignore_above": 1024 + }, + "ja3s": { + "type": "keyword", + "ignore_above": 1024 + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "subject": { + "type": "keyword", + "ignore_above": 1024 + }, + "x509": { + "properties": { + "alternative_names": { + "type": "keyword", + "ignore_above": 1024 + }, + "issuer": { + "properties": { + "common_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country": { + "type": "keyword", + "ignore_above": 1024 + }, + "distinguished_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "locality": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "organizational_unit": { + "type": "keyword", + "ignore_above": 1024 + }, + "state_or_province": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "not_after": { + "type": "date" + }, + "not_before": { + "type": "date" + }, + "public_key_algorithm": { + "type": "keyword", + "ignore_above": 1024 + }, + "public_key_curve": { + "type": "keyword", + "ignore_above": 1024 + }, + "public_key_exponent": { + "type": "long", + "index": false, + "doc_values": false + }, + "public_key_size": { + "type": "long" + }, + "serial_number": { + "type": "keyword", + "ignore_above": 1024 + }, + "signature_algorithm": { + "type": "keyword", + "ignore_above": 1024 + }, + "subject": { + "properties": { + "common_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "country": { + "type": "keyword", + "ignore_above": 1024 + }, + "distinguished_name": { + "type": "keyword", + "ignore_above": 1024 + }, + "locality": { + "type": "keyword", + "ignore_above": 1024 + }, + "organization": { + "type": "keyword", + "ignore_above": 1024 + }, + "organizational_unit": { + "type": "keyword", + "ignore_above": 1024 + }, + "state_or_province": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "version_number": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + }, + "version_protocol": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "trace": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "transaction": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "url": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "extension": { + "type": "keyword", + "ignore_above": 1024 + }, + "fragment": { + "type": "keyword", + "ignore_above": 1024 + }, + "full": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "original": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "password": { + "type": "keyword", + "ignore_above": 1024 + }, + "path": { + "type": "keyword", + "ignore_above": 1024 + }, + "port": { + "type": "long" + }, + "query": { + "type": "keyword", + "ignore_above": 1024 + }, + "registered_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "scheme": { + "type": "keyword", + "ignore_above": 1024 + }, + "subdomain": { + "type": "keyword", + "ignore_above": 1024 + }, + "top_level_domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "username": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "user": { + "properties": { + "changes": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "effective": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + }, + "target": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "email": { + "type": "keyword", + "ignore_above": 1024 + }, + "full_name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "group": { + "properties": { + "domain": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "hash": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "roles": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "user_agent": { + "properties": { + "device": { + "properties": { + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + }, + "original": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "os": { + "properties": { + "family": { + "type": "keyword", + "ignore_above": 1024 + }, + "full": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "kernel": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "platform": { + "type": "keyword", + "ignore_above": 1024 + }, + "type": { + "type": "keyword", + "ignore_above": 1024 + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "vlan": { + "properties": { + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "name": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "vulnerability": { + "properties": { + "category": { + "type": "keyword", + "ignore_above": 1024 + }, + "classification": { + "type": "keyword", + "ignore_above": 1024 + }, + "description": { + "type": "keyword", + "ignore_above": 1024, + "fields": { + "text": { + "type": "text", + "norms": false + } + } + }, + "enumeration": { + "type": "keyword", + "ignore_above": 1024 + }, + "id": { + "type": "keyword", + "ignore_above": 1024 + }, + "reference": { + "type": "keyword", + "ignore_above": 1024 + }, + "report_id": { + "type": "keyword", + "ignore_above": 1024 + }, + "scanner": { + "properties": { + "vendor": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "score": { + "properties": { + "base": { + "type": "float" + }, + "environmental": { + "type": "float" + }, + "temporal": { + "type": "float" + }, + "version": { + "type": "keyword", + "ignore_above": 1024 + } + } + }, + "severity": { + "type": "keyword", + "ignore_above": 1024 + } + } + } + } + }, + "settings": { + "index": { + "lifecycle": { + "name": ".siem-signals-default", + "rollover_alias": ".siem-signals-default" + }, + "routing": { + "allocation": { + "include": { + "_tier_preference": "data_content" + } + } + }, + "mapping": { + "total_fields": { + "limit": "10000" + } + }, + "number_of_shards": "1", + "number_of_replicas": "1" + } + } + } +} \ No newline at end of file From 50f99676bf27ccae5d6ac97cab7b573330554a8c Mon Sep 17 00:00:00 2001 From: Chris Roberson Date: Tue, 29 Mar 2022 10:50:00 -0400 Subject: [PATCH 25/31] [Response Ops] Alerts table (#125977) * WIP * Fix some issues * WIP * Revert "WIP" This reverts commit 5583997921dca184227b9e1c84b1030bad2fbda1. * WIP * Mock data * WIP * WIP * Remove unnecessary logic * Add some basic tests * Slight rename * Fix unnecessary export * Fix types * Add ability to use externally * Add test data * Fix types and tests * LAZZYYYYYYY load * Improvements based on o11y integrations * Fix types and tests * Cleanup and unit tests * Better integration with o11y alerts * Use experimental flag * Add functional tests * Fix tests * Add unit test for home page, and stop using internal because we have the feature flag * Fix bad label * Update strategy name * Fix test * Fix test, part 2 Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/rule_registry/common/index.ts | 6 +- .../common/experimental_features.ts | 1 + .../public/application/app.tsx | 2 +- .../public/application/constants/index.ts | 3 +- .../public/application/home.test.tsx | 43 ++++ .../public/application/home.tsx | 29 ++- .../alerts_table/alerts_page/README.md | 1 + .../alerts_table/alerts_page/alerts_page.tsx | 195 ++++++++++++++++++ .../alerts_table/alerts_page/index.ts | 9 + .../alerts_table/alerts_table.test.tsx | 106 ++++++++++ .../sections/alerts_table/alerts_table.tsx | 46 +++++ .../sections/alerts_table/hooks/index.ts | 8 + .../alerts_table/hooks/use_pagination.test.ts | 45 ++++ .../alerts_table/hooks/use_pagination.ts | 38 ++++ .../alerts_table/hooks/use_sorting.test.ts | 33 +++ .../alerts_table/hooks/use_sorting.ts | 21 ++ .../sections/alerts_table/index.ts | 10 + .../sections/alerts_table/types.ts | 12 ++ .../public/common/get_alerts_table.tsx | 14 ++ .../common/get_experimental_features.test.tsx | 12 +- .../common/get_experimental_features.ts | 4 +- .../triggers_actions_ui/public/mocks.ts | 5 + .../triggers_actions_ui/public/plugin.ts | 6 + .../triggers_actions_ui/public/types.ts | 47 ++++- .../apps/triggers_actions_ui/alerts_table.ts | 157 ++++++++++++++ .../apps/triggers_actions_ui/index.ts | 1 + x-pack/test/functional_with_es_ssl/config.ts | 1 + 27 files changed, 846 insertions(+), 9 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/README.md create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/alerts_page.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/index.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.test.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/index.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.test.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.test.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/index.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/types.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/common/get_alerts_table.tsx create mode 100644 x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_table.ts diff --git a/x-pack/plugins/rule_registry/common/index.ts b/x-pack/plugins/rule_registry/common/index.ts index 2dd7f6bbc456e..1f6053735d9b7 100644 --- a/x-pack/plugins/rule_registry/common/index.ts +++ b/x-pack/plugins/rule_registry/common/index.ts @@ -5,5 +5,9 @@ * 2.0. */ export { parseTechnicalFields, type ParsedTechnicalFields } from './parse_technical_fields'; -export type { RuleRegistrySearchRequest, RuleRegistrySearchResponse } from './search_strategy'; +export type { + RuleRegistrySearchRequest, + RuleRegistrySearchResponse, + RuleRegistrySearchRequestPagination, +} from './search_strategy'; export { BASE_RAC_ALERTS_API_PATH } from './constants'; diff --git a/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts b/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts index c3ae062d76523..f95ce25122923 100644 --- a/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts +++ b/x-pack/plugins/triggers_actions_ui/common/experimental_features.ts @@ -13,6 +13,7 @@ export type ExperimentalFeatures = typeof allowedExperimentalValues; */ export const allowedExperimentalValues = Object.freeze({ rulesListDatagrid: true, + internalAlertsTable: false, rulesDetailLogs: true, }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx index b2c350a4f1f29..0701eac20a850 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/app.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/app.tsx @@ -59,7 +59,7 @@ export const renderApp = (deps: TriggersAndActionsUiServices) => { export const App = ({ deps }: { deps: TriggersAndActionsUiServices }) => { const { savedObjects, uiSettings, theme$ } = deps; - const sections: Section[] = ['rules', 'connectors']; + const sections: Section[] = ['rules', 'connectors', 'alerts']; const isDarkMode = useObservable(uiSettings.get$('theme:darkMode')); const sectionsRegex = sections.join('|'); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts index 0058147ca0d05..0d26abc3bc67b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/constants/index.ts @@ -13,12 +13,13 @@ export { } from '../../../../alerting/common'; export { BASE_ACTION_API_PATH, INTERNAL_BASE_ACTION_API_PATH } from '../../../../actions/common'; -export type Section = 'connectors' | 'rules'; +export type Section = 'connectors' | 'rules' | 'alerts'; export const routeToHome = `/`; export const routeToConnectors = `/connectors`; export const routeToRules = `/rules`; export const routeToRuleDetails = `/rule/:ruleId`; +export const routeToInternalAlerts = `/alerts`; export const legacyRouteToRules = `/alerts`; export const legacyRouteToRuleDetails = `/alert/:alertId`; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx index 51f80438c55cc..6236e9e2d3d27 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.test.tsx @@ -10,11 +10,20 @@ import { RouteComponentProps, Router } from 'react-router-dom'; import { createMemoryHistory, createLocation } from 'history'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import TriggersActionsUIHome, { MatchParams } from './home'; +import { hasShowActionsCapability } from './lib/capabilities'; import { useKibana } from '../common/lib/kibana'; +import { getIsExperimentalFeatureEnabled } from '../common/get_experimental_features'; jest.mock('../common/lib/kibana'); +jest.mock('../common/get_experimental_features'); +jest.mock('./lib/capabilities'); const useKibanaMock = useKibana as jest.Mocked; describe('home', () => { + beforeEach(() => { + (hasShowActionsCapability as jest.Mock).mockClear(); + (getIsExperimentalFeatureEnabled as jest.Mock).mockClear(); + }); + it('renders the documentation link', async () => { const props: RouteComponentProps = { history: createMemoryHistory(), @@ -40,4 +49,38 @@ describe('home', () => { 'https://www.elastic.co/guide/en/kibana/mocked-test-branch/create-and-manage-rules.html' ); }); + + it('hides the internal alerts table route if the config is not set', async () => { + (hasShowActionsCapability as jest.Mock).mockImplementation(() => { + return true; + }); + const props: RouteComponentProps = { + history: createMemoryHistory(), + location: createLocation('/'), + match: { + isExact: true, + path: `/connectorss`, + url: '', + params: { + section: 'connectors', + }, + }, + }; + + let home = mountWithIntl(); + + // Just rules/connectors + expect(home.find('.euiTab__content').length).toBe(2); + + (getIsExperimentalFeatureEnabled as jest.Mock).mockImplementation((feature: string) => { + if (feature === 'internalAlertsTable') { + return true; + } + return false; + }); + + home = mountWithIntl(); + // alerts now too! + expect(home.find('.euiTab__content').length).toBe(3); + }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx index 1489397e1e7e3..9110ebe1f51c8 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/home.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/home.tsx @@ -6,11 +6,12 @@ */ import React, { lazy, useEffect } from 'react'; -import { Route, RouteComponentProps, Switch } from 'react-router-dom'; +import { Route, RouteComponentProps, Switch, Redirect } from 'react-router-dom'; import { FormattedMessage } from '@kbn/i18n-react'; import { EuiSpacer, EuiButtonEmpty, EuiPageHeader } from '@elastic/eui'; -import { Section, routeToConnectors, routeToRules } from './constants'; +import { getIsExperimentalFeatureEnabled } from '../common/get_experimental_features'; +import { Section, routeToConnectors, routeToRules, routeToInternalAlerts } from './constants'; import { getAlertingSectionBreadcrumb } from './lib/breadcrumb'; import { getCurrentDocTitle } from './lib/doc_title'; import { hasShowActionsCapability } from './lib/capabilities'; @@ -24,6 +25,7 @@ const ActionsConnectorsList = lazy( () => import('./sections/actions_connectors_list/components/actions_connectors_list') ); const RulesList = lazy(() => import('./sections/rules_list/components/rules_list')); +const AlertsPage = lazy(() => import('./sections/alerts_table/alerts_page')); export interface MatchParams { section: Section; @@ -38,9 +40,11 @@ export const TriggersActionsUIHome: React.FunctionComponent + ), + }); + } + const onSectionChange = (newSection: Section) => { history.push(`/${newSection}`); }; @@ -134,6 +150,15 @@ export const TriggersActionsUIHome: React.FunctionComponent + {isInternalAlertsTableEnabled ? ( + + ) : ( + + )} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/README.md b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/README.md new file mode 100644 index 0000000000000..6e57a57f7abdf --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/README.md @@ -0,0 +1 @@ +Note: This entire folder is meant for internal, testing purposes and is not exposed to users. \ No newline at end of file diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/alerts_page.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/alerts_page.tsx new file mode 100644 index 0000000000000..c3c02dd064bcb --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/alerts_page.tsx @@ -0,0 +1,195 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useState, useCallback, useEffect } from 'react'; +import { get } from 'lodash'; +import { + EuiDataGridCellValueElementProps, + EuiDataGridControlColumn, + EuiFlexItem, + EuiFlexGroup, + EuiSpacer, + EuiProgress, +} from '@elastic/eui'; +import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey'; +import { AlertConsumers } from '@kbn/rule-data-utils'; +import { + RuleRegistrySearchRequest, + RuleRegistrySearchResponse, + RuleRegistrySearchRequestPagination, +} from '../../../../../../rule_registry/common'; +import { AlertsTable } from '../alerts_table'; +import { useKibana } from '../../../../common/lib/kibana'; +import { AbortError } from '../../../../../../../../src/plugins/kibana_utils/common'; +import { AlertsData } from '../../../../types'; + +const consumers = [ + AlertConsumers.APM, + AlertConsumers.LOGS, + AlertConsumers.UPTIME, + AlertConsumers.INFRASTRUCTURE, +]; + +const defaultPagination = { + pageSize: 10, + pageIndex: 0, +}; + +const defaultSort: estypes.SortCombinations[] = [ + { + 'event.action': { + order: 'asc', + }, + }, +]; + +const AlertsPage: React.FunctionComponent = () => { + const { data, notifications } = useKibana().services; + const [showCheckboxes] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const [isInitializing, setIsInitializing] = useState(true); + const [alertsCount, setAlertsCount] = useState(0); + const [alerts, setAlerts] = useState([]); + const [sort, setSort] = useState(defaultSort); + const [pagination, setPagination] = useState(defaultPagination); + + const onPageChange = (_pagination: RuleRegistrySearchRequestPagination) => { + setPagination(_pagination); + }; + const onSortChange = (_sort: Array<{ id: string; direction: 'asc' | 'desc' }>) => { + setSort( + _sort.map(({ id, direction }) => { + return { + [id]: { + order: direction, + }, + }; + }) + ); + }; + + const asyncSearch = useCallback(() => { + setIsLoading(true); + const abortController = new AbortController(); + const request: RuleRegistrySearchRequest = { + featureIds: consumers, + sort, + pagination, + }; + data.search + .search(request, { + strategy: 'privateRuleRegistryAlertsSearchStrategy', + abortSignal: abortController.signal, + }) + .subscribe({ + next: (res) => { + const alertsResponse = res.rawResponse.hits.hits.map( + (hit) => hit.fields as unknown as AlertsData + ) as AlertsData[]; + setAlerts(alertsResponse); + const total = !isNaN(res.rawResponse.hits.total as number) + ? (res.rawResponse.hits.total as number) + : (res.rawResponse.hits.total as estypes.SearchTotalHits).value ?? 0; + setAlertsCount(total); + setIsLoading(false); + }, + error: (e) => { + if (e instanceof AbortError) { + notifications.toasts.addWarning({ + title: e.message, + }); + } else { + notifications.toasts.addDanger({ + title: 'Failed to run search', + text: e.message, + }); + } + setIsLoading(false); + }, + }); + setIsInitializing(false); + }, [data.search, notifications.toasts, sort, pagination]); + + useEffect(() => { + asyncSearch(); + }, [asyncSearch]); + + const useFetchAlertsData = () => { + return { + activePage: pagination.pageIndex, + alerts, + alertsCount, + isInitializing, + isLoading, + getInspectQuery: () => ({ request: {}, response: {} }), + onColumnsChange: (columns: EuiDataGridControlColumn[]) => {}, + onPageChange, + onSortChange, + refresh: () => { + asyncSearch(); + }, + }; + }; + + const tableProps = { + consumers, + bulkActions: [], + columns: [ + { + id: 'event.action', + displayAsText: 'Alert status', + initialWidth: 150, + }, + { + id: '@timestamp', + displayAsText: 'Last updated', + initialWidth: 250, + }, + { + id: 'kibana.alert.duration.us', + displayAsText: 'Duration', + initialWidth: 150, + }, + { + id: 'kibana.alert.reason', + displayAsText: 'Reason', + }, + ], + deletedEventIds: [], + disabledCellActions: [], + pageSize: defaultPagination.pageSize, + pageSizeOptions: [2, 5, 10, 20, 50, 100], + leadingControlColumns: [], + renderCellValue: (rcvProps: EuiDataGridCellValueElementProps) => { + const { columnId, visibleRowIndex } = rcvProps as EuiDataGridCellValueElementProps & { + visibleRowIndex: number; + }; + const value = (get(alerts[visibleRowIndex], columnId) ?? [])[0]; + return value ?? 'N/A'; + }, + showCheckboxes, + trailingControlColumns: [], + useFetchAlertsData, + 'data-test-subj': 'internalAlertsPage', + }; + + return ( +
+

THIS IS AN INTERNAL TEST PAGE

+ + + + {isLoading && ( + + )} + + + +
+ ); +}; + +export { AlertsPage }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/index.ts new file mode 100644 index 0000000000000..c574bda7f14ff --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_page/index.ts @@ -0,0 +1,9 @@ +/* + * 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 { AlertsPage } from './alerts_page'; +// eslint-disable-next-line import/no-default-export +export { AlertsPage as default }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.test.tsx new file mode 100644 index 0000000000000..c0a50e460fe8a --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.test.tsx @@ -0,0 +1,106 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { mountWithIntl, nextTick } from '@kbn/test-jest-helpers'; +import { act } from 'react-dom/test-utils'; +import { AlertConsumers } from '@kbn/rule-data-utils'; +import { AlertsTable } from './alerts_table'; +import { AlertsData } from '../../../types'; +jest.mock('../../../../../../../src/plugins/data/public/'); +jest.mock('../../../common/lib/kibana'); + +describe('AlertsTable', () => { + const consumers = [ + AlertConsumers.APM, + AlertConsumers.LOGS, + AlertConsumers.UPTIME, + AlertConsumers.INFRASTRUCTURE, + AlertConsumers.SIEM, + ]; + const columns = [ + { + id: 'kibana.alert.rule.name', + displayAsText: 'Name', + }, + { + id: 'kibana.alert.rule.category', + displayAsText: 'Category', + }, + ]; + + const alerts: AlertsData[] = [ + { + field1: ['one'], + field2: ['two'], + }, + { + field1: ['three'], + field2: ['four'], + }, + ]; + const fetchAlertsData = { + activePage: 0, + alerts, + alertsCount: alerts.length, + isInitializing: false, + isLoading: false, + getInspectQuery: jest.fn().mockImplementation(() => ({ request: {}, response: {} })), + onColumnsChange: jest.fn(), + onPageChange: jest.fn(), + onSortChange: jest.fn(), + refresh: jest.fn(), + }; + const useFetchAlertsData = () => { + return fetchAlertsData; + }; + + const tableProps = { + consumers, + bulkActions: [], + columns, + deletedEventIds: [], + disabledCellActions: [], + pageSize: 1, + pageSizeOptions: [1, 2, 5, 10, 20, 50, 100], + leadingControlColumns: [], + renderCellValue: jest.fn().mockImplementation((props) => { + return `${props.colIndex}:${props.rowIndex}`; + }), + showCheckboxes: false, + trailingControlColumns: [], + useFetchAlertsData, + 'data-test-subj': 'testTable', + }; + + it('should support sorting', async () => { + const wrapper = mountWithIntl(); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + wrapper.find('.euiDataGridHeaderCell__button').first().simulate('click'); + wrapper.update(); + wrapper + .find(`[data-test-subj="dataGridHeaderCellActionGroup-${columns[0].id}"]`) + .first() + .simulate('click'); + wrapper.find(`.euiListGroupItem__label[title="Sort A-Z"]`).simulate('click'); + expect(fetchAlertsData.onSortChange).toHaveBeenCalledWith([ + { direction: 'asc', id: 'kibana.alert.rule.name' }, + ]); + }); + + it('should support pagination', async () => { + const wrapper = mountWithIntl(); + await act(async () => { + await nextTick(); + wrapper.update(); + }); + wrapper.find('.euiPagination__item EuiButtonEmpty').at(1).simulate('click'); + expect(fetchAlertsData.onPageChange).toHaveBeenCalledWith({ pageIndex: 1, pageSize: 1 }); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx new file mode 100644 index 0000000000000..2568c5b96407b --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/alerts_table.tsx @@ -0,0 +1,46 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React, { useState } from 'react'; +import { EuiDataGrid } from '@elastic/eui'; +import { useSorting, usePagination } from './hooks'; +import { AlertsTableProps } from '../../../types'; + +const AlertsTable: React.FunctionComponent = (props: AlertsTableProps) => { + const { activePage, alertsCount, onPageChange, onSortChange } = props.useFetchAlertsData(); + const { sortingColumns, onSort } = useSorting(onSortChange); + const { pagination, onChangePageSize, onChangePageIndex } = usePagination({ + onPageChange, + pageIndex: activePage, + pageSize: props.pageSize, + }); + + const [visibleColumns, setVisibleColumns] = useState(props.columns.map(({ id }) => id)); + + return ( +
+ +
+ ); +}; + +export { AlertsTable }; +// eslint-disable-next-line import/no-default-export +export { AlertsTable as default }; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/index.ts new file mode 100644 index 0000000000000..9da3178db8c39 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/index.ts @@ -0,0 +1,8 @@ +/* + * 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 { usePagination } from './use_pagination'; +export { useSorting } from './use_sorting'; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.test.ts new file mode 100644 index 0000000000000..8b8ff68f106c2 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.test.ts @@ -0,0 +1,45 @@ +/* + * 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 { usePagination } from './use_pagination'; +import { renderHook, act } from '@testing-library/react-hooks'; + +describe('usePagination', () => { + const onPageChange = jest.fn(); + const pageIndex = 0; + const pageSize = 10; + + beforeEach(() => { + onPageChange.mockClear(); + }); + + it('should return the pagination information and callback functions', () => { + const { result } = renderHook(() => usePagination({ onPageChange, pageIndex, pageSize })); + expect(result.current.pagination).toStrictEqual({ pageIndex, pageSize }); + expect(result.current.onChangePageSize).toBeDefined(); + expect(result.current.onChangePageIndex).toBeDefined(); + }); + + it('should change the pagination when `onChangePageSize` is called', () => { + const { result } = renderHook(() => usePagination({ onPageChange, pageIndex, pageSize })); + + act(() => { + result.current.onChangePageSize(20); + }); + + expect(result.current.pagination).toStrictEqual({ pageIndex, pageSize: 20 }); + }); + + it('should change the pagination when `onChangePageIndex` is called', () => { + const { result } = renderHook(() => usePagination({ onPageChange, pageIndex, pageSize })); + + act(() => { + result.current.onChangePageIndex(1); + }); + + expect(result.current.pagination).toStrictEqual({ pageIndex: 1, pageSize }); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.ts new file mode 100644 index 0000000000000..4f00e05ed1122 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_pagination.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 { useCallback, useState } from 'react'; +import { RuleRegistrySearchRequestPagination } from '../../../../../../rule_registry/common'; + +type PaginationProps = RuleRegistrySearchRequestPagination & { + onPageChange: (pagination: RuleRegistrySearchRequestPagination) => void; +}; + +export function usePagination({ onPageChange, pageIndex, pageSize }: PaginationProps) { + const [pagination, setPagination] = useState({ + pageIndex, + pageSize, + }); + const onChangePageSize = useCallback( + (_pageSize) => { + setPagination((state) => ({ + ...state, + pageSize: _pageSize, + pageIndex: 0, + })); + onPageChange({ pageIndex: 0, pageSize: _pageSize }); + }, + [setPagination, onPageChange] + ); + const onChangePageIndex = useCallback( + (_pageIndex) => { + setPagination((state) => ({ ...state, pageIndex: _pageIndex })); + onPageChange({ pageIndex: _pageIndex, pageSize: pagination.pageSize }); + }, + [setPagination, onPageChange, pagination.pageSize] + ); + return { pagination, onChangePageSize, onChangePageIndex }; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.test.ts new file mode 100644 index 0000000000000..487f6908a334e --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.test.ts @@ -0,0 +1,33 @@ +/* + * 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 { useSorting } from './use_sorting'; +import { renderHook, act } from '@testing-library/react-hooks'; + +describe('useSorting', () => { + const onSortChange = jest.fn(); + + beforeEach(() => { + onSortChange.mockClear(); + }); + + it('should return the sorted columns and the callback function to call when sort changes', () => { + const { result } = renderHook(() => useSorting(onSortChange)); + expect(result.current.sortingColumns).toStrictEqual([]); + expect(result.current.onSort).toBeDefined(); + }); + + it('should change the columns when `onSort` is called', () => { + const { result } = renderHook(() => useSorting(onSortChange)); + + act(() => { + result.current.onSort([{ id: 'field', direction: 'asc' }]); + }); + + expect(onSortChange).toHaveBeenCalledWith([{ direction: 'asc', id: 'field' }]); + expect(result.current.sortingColumns).toStrictEqual([{ direction: 'asc', id: 'field' }]); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.ts new file mode 100644 index 0000000000000..cbb84c95806a0 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/hooks/use_sorting.ts @@ -0,0 +1,21 @@ +/* + * 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 { useCallback, useState } from 'react'; + +export function useSorting( + onSortChange: (sort: Array<{ id: string; direction: 'asc' | 'desc' }>) => void +) { + const [sortingColumns, setSortingColumns] = useState([]); + const onSort = useCallback( + (_state) => { + onSortChange(_state); + setSortingColumns(_state); + }, + [setSortingColumns, onSortChange] + ); + return { sortingColumns, onSort }; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/index.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/index.ts new file mode 100644 index 0000000000000..7fec39ad65d57 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/index.ts @@ -0,0 +1,10 @@ +/* + * 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 { lazy } from 'react'; +import { suspendedComponentWithProps } from '../../lib/suspended_component_with_props'; + +export const AlertsTable = suspendedComponentWithProps(lazy(() => import('./alerts_table'))); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/types.ts b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/types.ts new file mode 100644 index 0000000000000..9622477db3a30 --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_table/types.ts @@ -0,0 +1,12 @@ +/* + * 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 { AlertConsumers } from '@kbn/rule-data-utils'; + +export interface Consumer { + id: AlertConsumers; + name: string; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_table.tsx b/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_table.tsx new file mode 100644 index 0000000000000..4c2727cd9976d --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_alerts_table.tsx @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { AlertsTable } from '../application/sections/alerts_table'; +import type { AlertsTableProps } from '../types'; + +export const getAlertsTableLazy = (props: AlertsTableProps) => { + return ; +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_experimental_features.test.tsx b/x-pack/plugins/triggers_actions_ui/public/common/get_experimental_features.test.tsx index 0b865eb5b61be..aa7de97a6c889 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/get_experimental_features.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_experimental_features.test.tsx @@ -5,14 +5,18 @@ * 2.0. */ +import { getExperimentalAllowedValues } from '../../common/experimental_features'; import { ExperimentalFeaturesService } from './experimental_features_service'; import { getIsExperimentalFeatureEnabled } from './get_experimental_features'; +const allowedExperimentalValueKeys = getExperimentalAllowedValues(); + describe('getIsExperimentalFeatureEnabled', () => { it('getIsExperimentalFeatureEnabled returns the flag enablement', async () => { ExperimentalFeaturesService.init({ experimentalFeatures: { rulesListDatagrid: true, + internalAlertsTable: true, rulesDetailLogs: true, }, }); @@ -25,8 +29,14 @@ describe('getIsExperimentalFeatureEnabled', () => { expect(result).toEqual(true); + result = getIsExperimentalFeatureEnabled('internalAlertsTable'); + + expect(result).toEqual(true); + expect(() => getIsExperimentalFeatureEnabled('doesNotExist' as any)).toThrowError( - 'Invalid enable value doesNotExist. Allowed values are: rulesListDatagrid, rulesDetailLogs' + `Invalid enable value doesNotExist. Allowed values are: ${allowedExperimentalValueKeys.join( + ', ' + )}` ); }); }); diff --git a/x-pack/plugins/triggers_actions_ui/public/common/get_experimental_features.ts b/x-pack/plugins/triggers_actions_ui/public/common/get_experimental_features.ts index 706af60579711..41a321bbd2981 100644 --- a/x-pack/plugins/triggers_actions_ui/public/common/get_experimental_features.ts +++ b/x-pack/plugins/triggers_actions_ui/public/common/get_experimental_features.ts @@ -7,10 +7,10 @@ import { ExperimentalFeatures, - allowedExperimentalValues, isValidExperimentalValue, getExperimentalAllowedValues, } from '../../common/experimental_features'; +import { ExperimentalFeaturesService } from './experimental_features_service'; const allowedExperimentalValueKeys = getExperimentalAllowedValues(); @@ -23,5 +23,5 @@ export const getIsExperimentalFeatureEnabled = (feature: keyof ExperimentalFeatu ); } - return allowedExperimentalValues[feature]; + return ExperimentalFeaturesService.get()[feature]; }; diff --git a/x-pack/plugins/triggers_actions_ui/public/mocks.ts b/x-pack/plugins/triggers_actions_ui/public/mocks.ts index 7a0420594118b..706a66963e22f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/mocks.ts +++ b/x-pack/plugins/triggers_actions_ui/public/mocks.ts @@ -20,7 +20,9 @@ import { RuleTypeModel, ConnectorAddFlyoutProps, ConnectorEditFlyoutProps, + AlertsTableProps, } from './types'; +import { getAlertsTableLazy } from './common/get_alerts_table'; function createStartMock(): TriggersAndActionsUIPublicPluginStart { const actionTypeRegistry = new TypeRegistry(); @@ -51,6 +53,9 @@ function createStartMock(): TriggersAndActionsUIPublicPluginStart { ruleTypeRegistry, }); }, + getAlertsTable: (props: AlertsTableProps) => { + return getAlertsTableLazy(props); + }, }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/plugin.ts b/x-pack/plugins/triggers_actions_ui/public/plugin.ts index afeff4ba8364e..1993f0f931e17 100644 --- a/x-pack/plugins/triggers_actions_ui/public/plugin.ts +++ b/x-pack/plugins/triggers_actions_ui/public/plugin.ts @@ -32,6 +32,7 @@ import { getAddConnectorFlyoutLazy } from './common/get_add_connector_flyout'; import { getEditConnectorFlyoutLazy } from './common/get_edit_connector_flyout'; import { getAddAlertFlyoutLazy } from './common/get_add_alert_flyout'; import { getEditAlertFlyoutLazy } from './common/get_edit_alert_flyout'; +import { getAlertsTableLazy } from './common/get_alerts_table'; import { ExperimentalFeaturesService } from './common/experimental_features_service'; import { ExperimentalFeatures, @@ -45,6 +46,7 @@ import type { RuleTypeModel, ConnectorAddFlyoutProps, ConnectorEditFlyoutProps, + AlertsTableProps, } from './types'; import { TriggersActionsUiConfigType } from '../common/types'; @@ -68,6 +70,7 @@ export interface TriggersAndActionsUIPublicPluginStart { getEditAlertFlyout: ( props: Omit ) => ReactElement; + getAlertsTable: (props: AlertsTableProps) => ReactElement; } interface PluginsSetup { @@ -215,6 +218,9 @@ export class Plugin ruleTypeRegistry: this.ruleTypeRegistry, }); }, + getAlertsTable: (props: AlertsTableProps) => { + return getAlertsTableLazy(props); + }, }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/types.ts b/x-pack/plugins/triggers_actions_ui/public/types.ts index 7a1efaed33abf..c459d118c69b9 100644 --- a/x-pack/plugins/triggers_actions_ui/public/types.ts +++ b/x-pack/plugins/triggers_actions_ui/public/types.ts @@ -8,9 +8,15 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import type { DocLinksStart } from 'kibana/public'; import { ComponentType } from 'react'; +import { AlertConsumers } from '@kbn/rule-data-utils'; import { ChartsPluginSetup } from 'src/plugins/charts/public'; import { DataPublicPluginStart } from 'src/plugins/data/public'; -import { IconType } from '@elastic/eui'; +import { + IconType, + EuiDataGridColumn, + EuiDataGridControlColumn, + EuiDataGridCellValueElementProps, +} from '@elastic/eui'; import { ActionType, AlertHistoryEsIndexConnectorId, @@ -38,6 +44,7 @@ import { ActionVariable, RuleType as CommonRuleType, } from '../../alerting/common'; +import { RuleRegistrySearchRequestPagination } from '../../rule_registry/common'; // In Triggers and Actions we treat all `Alert`s as `SanitizedRule` // so the `Params` is a black-box of Record @@ -355,3 +362,41 @@ export interface TriggersActionsUiConfig { enforce: boolean; }; } + +export type AlertsData = Record; + +export interface FetchAlertData { + activePage: number; + alerts: AlertsData[]; + alertsCount: number; + isInitializing: boolean; + isLoading: boolean; + getInspectQuery: () => { request: {}; response: {} }; + onColumnsChange: (columns: EuiDataGridControlColumn[]) => void; + onPageChange: (pagination: RuleRegistrySearchRequestPagination) => void; + onSortChange: (sort: Array<{ id: string; direction: 'asc' | 'desc' }>) => void; + refresh: () => void; +} + +export interface BulkActionsObjectProp { + alertStatusActions?: boolean; + onAlertStatusActionSuccess?: void; + onAlertStatusActionFailure?: void; +} + +export interface AlertsTableProps { + consumers: AlertConsumers[]; + bulkActions: BulkActionsObjectProp; + columns: EuiDataGridColumn[]; + // defaultCellActions: TGridCellAction[]; + deletedEventIds: string[]; + disabledCellActions: string[]; + pageSize: number; + pageSizeOptions: number[]; + leadingControlColumns: EuiDataGridControlColumn[]; + renderCellValue: (props: EuiDataGridCellValueElementProps) => React.ReactNode; + showCheckboxes: boolean; + trailingControlColumns: EuiDataGridControlColumn[]; + useFetchAlertsData: () => FetchAlertData; + 'data-test-subj': string; +} diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_table.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_table.ts new file mode 100644 index 0000000000000..f0797ffd54d91 --- /dev/null +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/alerts_table.ts @@ -0,0 +1,157 @@ +/* + * 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 expect from '@kbn/expect'; +import { FtrProviderContext } from '../../ftr_provider_context'; + +export default ({ getPageObjects, getService }: FtrProviderContext) => { + const testSubjects = getService('testSubjects'); + const PageObjects = getPageObjects(['common', 'triggersActionsUI', 'header']); + const retry = getService('retry'); + const esArchiver = getService('esArchiver'); + const find = getService('find'); + + describe('Alerts table', function () { + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); + }); + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); + }); + + it('should load the table', async () => { + await PageObjects.common.navigateToUrlWithBrowserHistory('triggersActions', '/alerts'); + const headingText = await PageObjects.triggersActionsUI.getSectionHeadingText(); + expect(headingText).to.be('Rules and Connectors'); + + await waitTableIsLoaded(); + + const euiDataGridRows = await find.allByCssSelector('.euiDataGridRow'); + const rows = []; + for (const euiDataGridRow of euiDataGridRows) { + const $ = await euiDataGridRow.parseDomContent(); + rows.push({ + status: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="event.action"] .euiDataGridRowCell__truncate') + .text(), + lastUpdated: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="@timestamp"] .euiDataGridRowCell__truncate') + .text(), + duration: $.findTestSubjects('dataGridRowCell') + .find( + '[data-gridcell-column-id="kibana.alert.duration.us"] .euiDataGridRowCell__truncate' + ) + .text(), + reason: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="kibana.alert.reason"] .euiDataGridRowCell__truncate') + .text(), + }); + } + expect(rows.length).to.be(10); + expect(rows[0].status).to.be('active'); + expect(rows[0].lastUpdated).to.be('2021-10-19T15:20:38.749Z'); + expect(rows[0].duration).to.be('1197194000'); + expect(rows[0].reason).to.be( + 'Failed transactions rate is greater than 5.0% (current value is 31%) for elastic-co-frontend' + ); + }); + + it('should sort properly', async () => { + await PageObjects.common.navigateToUrlWithBrowserHistory('triggersActions', '/alerts'); + const headingText = await PageObjects.triggersActionsUI.getSectionHeadingText(); + expect(headingText).to.be('Rules and Connectors'); + + await waitTableIsLoaded(); + + await find.clickDisplayedByCssSelector( + '[data-test-subj="dataGridHeaderCell-event.action"] .euiDataGridHeaderCell__button' + ); + + const popoverButtons = await testSubjects.find('dataGridHeaderCellActionGroup-event.action'); + await (await popoverButtons.findAllByCssSelector('.euiListGroupItem__button'))[2].click(); + + await waitTableIsLoaded(); + + const euiDataGridRows = await find.allByCssSelector('.euiDataGridRow'); + const rows = []; + for (const euiDataGridRow of euiDataGridRows) { + const $ = await euiDataGridRow.parseDomContent(); + rows.push({ + status: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="event.action"] .euiDataGridRowCell__truncate') + .text(), + lastUpdated: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="@timestamp"] .euiDataGridRowCell__truncate') + .text(), + duration: $.findTestSubjects('dataGridRowCell') + .find( + '[data-gridcell-column-id="kibana.alert.duration.us"] .euiDataGridRowCell__truncate' + ) + .text(), + reason: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="kibana.alert.reason"] .euiDataGridRowCell__truncate') + .text(), + }); + } + expect(rows.length).to.be(10); + expect(rows[0].status).to.be('open'); + expect(rows[0].lastUpdated).to.be('2021-10-19T15:20:26.974Z'); + expect(rows[0].duration).to.be('0'); + expect(rows[0].reason).to.be( + 'CPU usage is greater than a threshold of 40 (current value is 45.2%) for gke-edge-oblt-default-pool-350b44de-c3dd' + ); + }); + + it('should paginate properly', async () => { + await PageObjects.common.navigateToUrlWithBrowserHistory('triggersActions', '/alerts'); + const headingText = await PageObjects.triggersActionsUI.getSectionHeadingText(); + expect(headingText).to.be('Rules and Connectors'); + + await waitTableIsLoaded(); + + await testSubjects.click('pagination-button-1'); + + await waitTableIsLoaded(); + + const euiDataGridRows = await find.allByCssSelector('.euiDataGridRow'); + const rows = []; + for (const euiDataGridRow of euiDataGridRows) { + const $ = await euiDataGridRow.parseDomContent(); + rows.push({ + status: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="event.action"] .euiDataGridRowCell__truncate') + .text(), + lastUpdated: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="@timestamp"] .euiDataGridRowCell__truncate') + .text(), + duration: $.findTestSubjects('dataGridRowCell') + .find( + '[data-gridcell-column-id="kibana.alert.duration.us"] .euiDataGridRowCell__truncate' + ) + .text(), + reason: $.findTestSubjects('dataGridRowCell') + .find('[data-gridcell-column-id="kibana.alert.reason"] .euiDataGridRowCell__truncate') + .text(), + }); + } + expect(rows.length).to.be(10); + expect(rows[0].status).to.be('active'); + expect(rows[0].lastUpdated).to.be('2021-10-19T15:20:26.974Z'); + expect(rows[0].duration).to.be('63291000'); + expect(rows[0].reason).to.be( + 'CPU usage is greater than a threshold of 40 (current value is 40.8%) for gke-edge-oblt-default-pool-350b44de-3v4p' + ); + }); + + async function waitTableIsLoaded() { + return await retry.try(async () => { + const exists = await testSubjects.exists('internalAlertsPageLoading'); + if (exists) throw new Error('Still loading...'); + }); + } + }); +}; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts index e70d4fdc96f61..76a952c354ab4 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/index.ts @@ -15,5 +15,6 @@ export default ({ loadTestFile, getService }: FtrProviderContext) => { loadTestFile(require.resolve('./alert_create_flyout')); loadTestFile(require.resolve('./details')); loadTestFile(require.resolve('./connectors')); + loadTestFile(require.resolve('./alerts_table')); }); }; diff --git a/x-pack/test/functional_with_es_ssl/config.ts b/x-pack/test/functional_with_es_ssl/config.ts index b2b6735a99c8b..dc2f6b8618ce3 100644 --- a/x-pack/test/functional_with_es_ssl/config.ts +++ b/x-pack/test/functional_with_es_ssl/config.ts @@ -67,6 +67,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) { `--elasticsearch.hosts=https://${servers.elasticsearch.hostname}:${servers.elasticsearch.port}`, `--elasticsearch.ssl.certificateAuthorities=${CA_CERT_PATH}`, `--plugin-path=${join(__dirname, 'fixtures', 'plugins', 'alerts')}`, + `--xpack.trigger_actions_ui.enableExperimental=${JSON.stringify(['internalAlertsTable'])}`, `--xpack.alerting.rules.minimumScheduleInterval.value="2s"`, `--xpack.actions.enabledActionTypes=${JSON.stringify(enabledActionTypes)}`, `--xpack.actions.preconfiguredAlertHistoryEsIndex=false`, From 74450ad697f3a770f38a5123d400e0077cfe124b Mon Sep 17 00:00:00 2001 From: Candace Park <56409205+parkiino@users.noreply.github.com> Date: Tue, 29 Mar 2022 11:02:09 -0400 Subject: [PATCH 26/31] [Security Solution][Endpoint][Admin][Policy] Enable Policy list feature flag (#128698) --- .../plugins/security_solution/common/experimental_features.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts index 3a932238f3a34..a9cf3e4a8132e 100644 --- a/x-pack/plugins/security_solution/common/experimental_features.ts +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -24,7 +24,7 @@ export const allowedExperimentalValues = Object.freeze({ riskyUsersEnabled: false, securityRulesCancelEnabled: false, pendingActionResponsesWithAck: true, - policyListEnabled: false, + policyListEnabled: true, /** * This is used for enabling the end to end tests for the security_solution telemetry. From e906db25664b70bded74c2c7233abc9b15d67e68 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Tue, 29 Mar 2022 11:03:04 -0400 Subject: [PATCH 27/31] [Fleet] Merge settings & mappings component template in @package (#128498) --- .../fleet/server/constants/fleet_es_assets.ts | 3 +- .../plugins/fleet/server/constants/index.ts | 3 +- .../epm/elasticsearch/template/install.ts | 34 +- .../epm/__snapshots__/install_by_upload.snap | 735 ------------------ .../apis/epm/install_by_upload.ts | 4 +- .../apis/epm/install_overrides.ts | 23 +- .../apis/epm/install_remove_assets.ts | 45 +- .../apis/epm/update_assets.ts | 69 +- 8 files changed, 52 insertions(+), 864 deletions(-) delete mode 100644 x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap diff --git a/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts b/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts index 859a25a0ec7c7..56aaf450d46e9 100644 --- a/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts +++ b/x-pack/plugins/fleet/server/constants/fleet_es_assets.ts @@ -8,9 +8,8 @@ import { getESAssetMetadata } from '../services/epm/elasticsearch/meta'; const meta = getESAssetMetadata(); -export const MAPPINGS_TEMPLATE_SUFFIX = '@mappings'; -export const SETTINGS_TEMPLATE_SUFFIX = '@settings'; +export const PACKAGE_TEMPLATE_SUFFIX = '@package'; export const USER_SETTINGS_TEMPLATE_SUFFIX = '@custom'; diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index ec7a4a2664882..813f381ecc4fc 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -66,7 +66,6 @@ export { FLEET_FINAL_PIPELINE_ID, FLEET_FINAL_PIPELINE_CONTENT, FLEET_FINAL_PIPELINE_VERSION, - MAPPINGS_TEMPLATE_SUFFIX, - SETTINGS_TEMPLATE_SUFFIX, USER_SETTINGS_TEMPLATE_SUFFIX, + PACKAGE_TEMPLATE_SUFFIX, } from './fleet_es_assets'; diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts index f30971c0e7d5e..a77f843aef2d3 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/install.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { merge, cloneDeep } from 'lodash'; +import { merge } from 'lodash'; import Boom from '@hapi/boom'; import type { ElasticsearchClient, Logger, SavedObjectsClientContract } from 'src/core/server'; @@ -29,8 +29,7 @@ import { getAsset, getPathParts } from '../../archive'; import { removeAssetTypesFromInstalledEs, saveInstalledEsRefs } from '../../packages/install'; import { FLEET_COMPONENT_TEMPLATES, - MAPPINGS_TEMPLATE_SUFFIX, - SETTINGS_TEMPLATE_SUFFIX, + PACKAGE_TEMPLATE_SUFFIX, USER_SETTINGS_TEMPLATE_SUFFIX, } from '../../../../constants'; @@ -245,34 +244,28 @@ function buildComponentTemplates(params: { defaultSettings: IndexTemplate['template']['settings']; }) { const { templateName, registryElasticsearch, packageName, defaultSettings, mappings } = params; - const mappingsTemplateName = `${templateName}${MAPPINGS_TEMPLATE_SUFFIX}`; - const settingsTemplateName = `${templateName}${SETTINGS_TEMPLATE_SUFFIX}`; + const packageTemplateName = `${templateName}${PACKAGE_TEMPLATE_SUFFIX}`; const userSettingsTemplateName = `${templateName}${USER_SETTINGS_TEMPLATE_SUFFIX}`; const templatesMap: TemplateMap = {}; const _meta = getESAssetMetadata({ packageName }); const indexTemplateSettings = registryElasticsearch?.['index_template.settings'] ?? {}; - // @ts-expect-error no property .mapping (yes there is) - const indexTemplateMappingSettings = indexTemplateSettings?.index?.mapping; - const indexTemplateSettingsForTemplate = cloneDeep(indexTemplateSettings); - - // index.mapping settings must go on the mapping component template otherwise - // the template may be rejected e.g if nested_fields.limit has been increased - if (indexTemplateMappingSettings) { - // @ts-expect-error no property .mapping - delete indexTemplateSettingsForTemplate.index.mapping; - } - templatesMap[mappingsTemplateName] = { + const templateSettings = merge(defaultSettings, indexTemplateSettings); + + templatesMap[packageTemplateName] = { template: { settings: { + ...templateSettings, index: { + ...templateSettings.index, mapping: { + ...templateSettings?.mapping, total_fields: { + ...templateSettings?.mapping?.total_fields, limit: '10000', }, - ...indexTemplateMappingSettings, }, }, }, @@ -281,13 +274,6 @@ function buildComponentTemplates(params: { _meta, }; - templatesMap[settingsTemplateName] = { - template: { - settings: merge(defaultSettings, indexTemplateSettingsForTemplate), - }, - _meta, - }; - // return empty/stub template templatesMap[userSettingsTemplateName] = { template: { diff --git a/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap b/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap deleted file mode 100644 index 421a5fbdf1744..0000000000000 --- a/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap +++ /dev/null @@ -1,735 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Fleet Endpoints EPM Endpoints installs packages from direct upload should install a zip archive correctly and package info should return correctly after validation 1`] = ` -Object { - "assets": Object { - "elasticsearch": Object { - "ingest_pipeline": Array [ - Object { - "dataset": "access", - "file": "default.yml", - "path": "apache-0.1.4/data_stream/access/elasticsearch/ingest_pipeline/default.yml", - "pkgkey": "apache-0.1.4", - "service": "elasticsearch", - "type": "ingest_pipeline", - }, - Object { - "dataset": "error", - "file": "default.yml", - "path": "apache-0.1.4/data_stream/error/elasticsearch/ingest_pipeline/default.yml", - "pkgkey": "apache-0.1.4", - "service": "elasticsearch", - "type": "ingest_pipeline", - }, - ], - }, - "kibana": Object { - "dashboard": Array [ - Object { - "file": "apache-Logs-Apache-Dashboard-ecs.json", - "path": "apache-0.1.4/kibana/dashboard/apache-Logs-Apache-Dashboard-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "dashboard", - }, - Object { - "file": "apache-Metrics-Apache-HTTPD-server-status-ecs.json", - "path": "apache-0.1.4/kibana/dashboard/apache-Metrics-Apache-HTTPD-server-status-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "dashboard", - }, - ], - "search": Array [ - Object { - "file": "Apache-HTTPD-ecs.json", - "path": "apache-0.1.4/kibana/search/Apache-HTTPD-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "search", - }, - Object { - "file": "Apache-access-logs-ecs.json", - "path": "apache-0.1.4/kibana/search/Apache-access-logs-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "search", - }, - Object { - "file": "Apache-errors-log-ecs.json", - "path": "apache-0.1.4/kibana/search/Apache-errors-log-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "search", - }, - ], - "visualization": Array [ - Object { - "file": "Apache-HTTPD-CPU-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-HTTPD-CPU-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-HTTPD-Hostname-list-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-HTTPD-Hostname-list-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-HTTPD-Load1-slash-5-slash-15-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-HTTPD-Load1-slash-5-slash-15-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-HTTPD-Scoreboard-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-HTTPD-Scoreboard-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-HTTPD-Total-accesses-and-kbytes-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-HTTPD-Total-accesses-and-kbytes-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-HTTPD-Uptime-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-HTTPD-Uptime-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-HTTPD-Workers-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-HTTPD-Workers-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-access-unique-IPs-map-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-access-unique-IPs-map-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-browsers-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-browsers-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-error-logs-over-time-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-error-logs-over-time-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-operating-systems-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-operating-systems-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-response-codes-of-top-URLs-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-response-codes-of-top-URLs-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - Object { - "file": "Apache-response-codes-over-time-ecs.json", - "path": "apache-0.1.4/kibana/visualization/Apache-response-codes-over-time-ecs.json", - "pkgkey": "apache-0.1.4", - "service": "kibana", - "type": "visualization", - }, - ], - }, - }, - "categories": Array [ - "web", - ], - "conditions": Object { - "kibana": Object { - "version": "^7.9.0", - }, - }, - "data_streams": Array [ - Object { - "dataset": "apache.access", - "ingest_pipeline": "default", - "package": "apache", - "path": "access", - "release": "experimental", - "streams": Array [ - Object { - "description": "Collect Apache access logs", - "enabled": true, - "input": "logfile", - "template_path": "log.yml.hbs", - "title": "Apache access logs", - "vars": Array [ - Object { - "default": Array [ - "/var/log/apache2/access.log*", - "/var/log/apache2/other_vhosts_access.log*", - "/var/log/httpd/access_log*", - ], - "multi": true, - "name": "paths", - "required": true, - "show_user": true, - "title": "Paths", - "type": "text", - }, - ], - }, - ], - "title": "Apache access logs", - "type": "logs", - }, - Object { - "dataset": "apache.error", - "ingest_pipeline": "default", - "package": "apache", - "path": "error", - "release": "experimental", - "streams": Array [ - Object { - "description": "Collect Apache error logs", - "enabled": true, - "input": "logfile", - "template_path": "log.yml.hbs", - "title": "Apache error logs", - "vars": Array [ - Object { - "default": Array [ - "/var/log/apache2/error.log*", - "/var/log/httpd/error_log*", - ], - "multi": true, - "name": "paths", - "required": true, - "show_user": true, - "title": "Paths", - "type": "text", - }, - ], - }, - ], - "title": "Apache error logs", - "type": "logs", - }, - Object { - "dataset": "apache.status", - "package": "apache", - "path": "status", - "release": "experimental", - "streams": Array [ - Object { - "description": "Collect Apache status metrics", - "enabled": true, - "input": "apache/metrics", - "template_path": "stream.yml.hbs", - "title": "Apache status metrics", - "vars": Array [ - Object { - "default": "10s", - "multi": false, - "name": "period", - "required": true, - "show_user": true, - "title": "Period", - "type": "text", - }, - Object { - "default": "/server-status", - "multi": false, - "name": "server_status_path", - "required": true, - "show_user": false, - "title": "Server Status Path", - "type": "text", - }, - ], - }, - ], - "title": "Apache status metrics", - "type": "metrics", - }, - ], - "description": "Apache Integration", - "download": "/epr/apache/apache-0.1.4.zip", - "format_version": "1.0.0", - "icons": Array [ - Object { - "path": "/package/apache/0.1.4/img/logo_apache.svg", - "size": "32x32", - "src": "/img/logo_apache.svg", - "title": "Apache Logo", - "type": "image/svg+xml", - }, - ], - "keepPoliciesUpToDate": false, - "license": "basic", - "name": "apache", - "owner": Object { - "github": "elastic/integrations-services", - }, - "path": "/package/apache/0.1.4", - "policy_templates": Array [ - Object { - "description": "Collect logs and metrics from Apache instances", - "inputs": Array [ - Object { - "description": "Collecting Apache access and error logs", - "title": "Collect logs from Apache instances", - "type": "logfile", - }, - Object { - "description": "Collecting Apache status metrics", - "title": "Collect metrics from Apache instances", - "type": "apache/metrics", - "vars": Array [ - Object { - "default": Array [ - "http://127.0.0.1", - ], - "multi": true, - "name": "hosts", - "required": true, - "show_user": true, - "title": "Hosts", - "type": "text", - }, - ], - }, - ], - "multiple": true, - "name": "apache", - "title": "Apache logs and metrics", - }, - ], - "readme": "/package/apache/0.1.4/docs/README.md", - "release": "experimental", - "removable": true, - "savedObject": Object { - "attributes": Object { - "es_index_patterns": Object { - "access": "logs-apache.access-*", - "error": "logs-apache.error-*", - "status": "metrics-apache.status-*", - }, - "install_source": "upload", - "install_status": "installed", - "install_version": "0.1.4", - "installed_es": Array [ - Object { - "id": "logs-apache.access-0.1.4-default", - "type": "ingest_pipeline", - }, - Object { - "id": "logs-apache.error-0.1.4-default", - "type": "ingest_pipeline", - }, - Object { - "id": "logs-apache.access", - "type": "index_template", - }, - Object { - "id": "logs-apache.access@mappings", - "type": "component_template", - }, - Object { - "id": "logs-apache.access@settings", - "type": "component_template", - }, - Object { - "id": "logs-apache.access@custom", - "type": "component_template", - }, - Object { - "id": "metrics-apache.status", - "type": "index_template", - }, - Object { - "id": "metrics-apache.status@mappings", - "type": "component_template", - }, - Object { - "id": "metrics-apache.status@settings", - "type": "component_template", - }, - Object { - "id": "metrics-apache.status@custom", - "type": "component_template", - }, - Object { - "id": "logs-apache.error", - "type": "index_template", - }, - Object { - "id": "logs-apache.error@mappings", - "type": "component_template", - }, - Object { - "id": "logs-apache.error@settings", - "type": "component_template", - }, - Object { - "id": "logs-apache.error@custom", - "type": "component_template", - }, - ], - "installed_kibana": Array [ - Object { - "id": "apache-Logs-Apache-Dashboard-ecs", - "type": "dashboard", - }, - Object { - "id": "apache-Metrics-Apache-HTTPD-server-status-ecs", - "type": "dashboard", - }, - Object { - "id": "Apache-access-unique-IPs-map-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-HTTPD-CPU-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-HTTPD-Load1-slash-5-slash-15-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-response-codes-over-time-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-HTTPD-Workers-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-HTTPD-Hostname-list-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-error-logs-over-time-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-HTTPD-Scoreboard-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-HTTPD-Uptime-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-operating-systems-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-HTTPD-Total-accesses-and-kbytes-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-browsers-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-response-codes-of-top-URLs-ecs", - "type": "visualization", - }, - Object { - "id": "Apache-access-logs-ecs", - "type": "search", - }, - Object { - "id": "Apache-errors-log-ecs", - "type": "search", - }, - Object { - "id": "Apache-HTTPD-ecs", - "type": "search", - }, - ], - "installed_kibana_space_id": "default", - "name": "apache", - "package_assets": Array [ - Object { - "id": "2f1ab9c0-8cf6-5e83-afcd-0d12851c8108", - "type": "epm-packages-assets", - }, - Object { - "id": "841166f1-6db0-5f7a-a8d9-768e88ddf984", - "type": "epm-packages-assets", - }, - Object { - "id": "b12ae5e1-daf2-51a7-99d8-0888d1f13b5b", - "type": "epm-packages-assets", - }, - Object { - "id": "2f263b24-c36a-5ea8-a707-76d1f274c888", - "type": "epm-packages-assets", - }, - Object { - "id": "bd5ff9ad-ba4a-5215-b5af-cef58a3aa886", - "type": "epm-packages-assets", - }, - Object { - "id": "5fc59aa9-1d7e-50ae-8ce5-b875ab44cfc5", - "type": "epm-packages-assets", - }, - Object { - "id": "7c850453-346b-5010-a946-28b83fc69e48", - "type": "epm-packages-assets", - }, - Object { - "id": "f02f8adb-3e0c-5f2f-b4f2-a04dc645b713", - "type": "epm-packages-assets", - }, - Object { - "id": "889d88db-6214-5836-aeff-1a87f8513b27", - "type": "epm-packages-assets", - }, - Object { - "id": "06a6b940-a745-563c-abf4-83eb3335926b", - "type": "epm-packages-assets", - }, - Object { - "id": "e68fd7ac-302e-5b75-bbbb-d69b441c8848", - "type": "epm-packages-assets", - }, - Object { - "id": "2c57fe0f-3b1a-57da-a63b-28f9b9e82bce", - "type": "epm-packages-assets", - }, - Object { - "id": "13db43e8-f8f9-57f0-b131-a171c2f2070f", - "type": "epm-packages-assets", - }, - Object { - "id": "e8750081-1c0b-5c55-bcab-fa6d47f01a85", - "type": "epm-packages-assets", - }, - Object { - "id": "71af57fe-25c4-5935-9879-ca4a2fba730e", - "type": "epm-packages-assets", - }, - Object { - "id": "cc287718-9573-5c56-a9ed-6dfef6589506", - "type": "epm-packages-assets", - }, - Object { - "id": "8badd8ba-289a-5e60-a1c0-f3d39e15cda3", - "type": "epm-packages-assets", - }, - Object { - "id": "20300efc-10eb-5fac-ba90-f6aa9b467e84", - "type": "epm-packages-assets", - }, - Object { - "id": "047c89df-33c2-5d74-b0a4-8b441879761c", - "type": "epm-packages-assets", - }, - Object { - "id": "9838a13f-1b89-5c54-844e-978620d66a1d", - "type": "epm-packages-assets", - }, - Object { - "id": "e105414b-221d-5433-8b24-452625f59b7c", - "type": "epm-packages-assets", - }, - Object { - "id": "eb166c25-843b-5271-8d43-6fb005d2df5a", - "type": "epm-packages-assets", - }, - Object { - "id": "342dbf4d-d88d-53e8-b365-d3639ebbbb14", - "type": "epm-packages-assets", - }, - Object { - "id": "f98c44a3-eaea-505f-8598-3b7f1097ef59", - "type": "epm-packages-assets", - }, - Object { - "id": "12da8c6c-d0e3-589c-9244-88d857ea76b6", - "type": "epm-packages-assets", - }, - Object { - "id": "e2d151ed-709c-542d-b797-cb95f353b9b3", - "type": "epm-packages-assets", - }, - Object { - "id": "f434cffe-0b00-59de-a17f-c1e71bd4ab0f", - "type": "epm-packages-assets", - }, - Object { - "id": "5bd0c25f-04a5-5fd0-8298-ba9aa2f6fe5e", - "type": "epm-packages-assets", - }, - Object { - "id": "279da3a3-8e9b-589b-86e0-bd7364821bab", - "type": "epm-packages-assets", - }, - Object { - "id": "b8758fcb-08bf-50fa-89bd-24398955298a", - "type": "epm-packages-assets", - }, - Object { - "id": "96e4eb36-03c3-5856-af44-559fd5133f2b", - "type": "epm-packages-assets", - }, - Object { - "id": "a59a79c3-66bd-5cfc-91f5-ee84f7227855", - "type": "epm-packages-assets", - }, - Object { - "id": "395143f9-54bf-5b46-b1be-a7b2a6142ad9", - "type": "epm-packages-assets", - }, - Object { - "id": "3449b8d2-ffd5-5aec-bb32-4245f2fbcde4", - "type": "epm-packages-assets", - }, - Object { - "id": "ab44094e-6c9d-50b8-b5c4-2e518d89912e", - "type": "epm-packages-assets", - }, - Object { - "id": "b093bfc0-6e98-5a1b-a502-e838a36f6568", - "type": "epm-packages-assets", - }, - Object { - "id": "03d86823-b756-5b91-850d-7ad231d33546", - "type": "epm-packages-assets", - }, - Object { - "id": "a76af2f0-049b-5be1-8d20-e87c9d1c2709", - "type": "epm-packages-assets", - }, - Object { - "id": "bc2f0c1e-992e-5407-9435-fedb39ff74ea", - "type": "epm-packages-assets", - }, - Object { - "id": "84668ac1-d5ef-545b-88f3-1e49f8f1c8ad", - "type": "epm-packages-assets", - }, - Object { - "id": "69b41271-91a0-5a2e-a62c-60364d5a9c8f", - "type": "epm-packages-assets", - }, - Object { - "id": "8e4ec555-5fbf-55d3-bea3-3af12c9aca3f", - "type": "epm-packages-assets", - }, - Object { - "id": "aa18f3f9-f62a-5ab8-9b34-75696efa5c48", - "type": "epm-packages-assets", - }, - Object { - "id": "71c8c6b1-2116-5817-b65f-7a87ef5ef2b7", - "type": "epm-packages-assets", - }, - Object { - "id": "8f6d7a1f-1e7f-5a60-8fe7-ce19115ed460", - "type": "epm-packages-assets", - }, - Object { - "id": "c115dbbf-edad-59f2-b046-c65a0373a81c", - "type": "epm-packages-assets", - }, - Object { - "id": "b7d696c3-8106-585c-9ecc-94a75cf1e3da", - "type": "epm-packages-assets", - }, - Object { - "id": "639e6a78-59d8-5ce8-9687-64e8f9af7e71", - "type": "epm-packages-assets", - }, - Object { - "id": "ae60c853-7a90-58d2-ab6c-04d3be5f1847", - "type": "epm-packages-assets", - }, - Object { - "id": "0cd33163-2ae4-57eb-96f6-c50af6685cab", - "type": "epm-packages-assets", - }, - Object { - "id": "39e0f78f-1172-5e61-9446-65ef3c0cb46c", - "type": "epm-packages-assets", - }, - Object { - "id": "b08f10ee-6afd-5e89-b9b4-569064fbdd9f", - "type": "epm-packages-assets", - }, - Object { - "id": "efcbe1c6-b2d5-521c-b27a-2146f08a604d", - "type": "epm-packages-assets", - }, - Object { - "id": "f9422c02-d43f-5ebb-b7c5-9e32f9b77c21", - "type": "epm-packages-assets", - }, - Object { - "id": "c276e880-3ba8-58e7-a5d5-c07707dba6b7", - "type": "epm-packages-assets", - }, - Object { - "id": "561a3711-c386-541c-9a77-2d0fa256caf6", - "type": "epm-packages-assets", - }, - Object { - "id": "1378350d-2e2b-52dd-ab3a-d8b9a09df92f", - "type": "epm-packages-assets", - }, - Object { - "id": "94e40729-4aea-59c8-86ba-075137c000dc", - "type": "epm-packages-assets", - }, - ], - "removable": true, - "version": "0.1.4", - }, - "id": "apache", - "namespaces": Array [], - "references": Array [], - "type": "epm-packages", - }, - "screenshots": Array [ - Object { - "path": "/package/apache/0.1.4/img/kibana-apache.png", - "size": "1215x1199", - "src": "/img/kibana-apache.png", - "title": "Apache Integration", - "type": "image/png", - }, - Object { - "path": "/package/apache/0.1.4/img/apache_httpd_server_status.png", - "size": "1919x1079", - "src": "/img/apache_httpd_server_status.png", - "title": "Apache HTTPD Server Status", - "type": "image/png", - }, - ], - "status": "installed", - "title": "Apache", - "type": "integration", - "version": "0.1.4", -} -`; diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts b/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts index 68cac70e8fed8..28b68609ce15e 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_by_upload.ts @@ -75,7 +75,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/gzip') .send(buf) .expect(200); - expect(res.body.items.length).to.be(32); + expect(res.body.items.length).to.be(29); }); it('should install a zip archive correctly and package info should return correctly after validation', async function () { @@ -86,7 +86,7 @@ export default function (providerContext: FtrProviderContext) { .type('application/zip') .send(buf) .expect(200); - expect(res.body.items.length).to.be(32); + expect(res.body.items.length).to.be(29); }); it('should throw an error if the archive is zip but content type is gzip', async function () { diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts b/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts index eee9525a4f062..834de2432d7c8 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_overrides.ts @@ -52,8 +52,7 @@ export default function (providerContext: FtrProviderContext) { // the index template composed_of has the correct component templates in the correct order const indexTemplate = indexTemplateResponse.index_templates[0].index_template; expect(indexTemplate.composed_of).to.eql([ - `${templateName}@mappings`, - `${templateName}@settings`, + `${templateName}@package`, `${templateName}@custom`, '.fleet_globals-1', '.fleet_agent_id_verification-1', @@ -62,25 +61,17 @@ export default function (providerContext: FtrProviderContext) { ({ body } = await es.transport.request( { method: 'GET', - path: `/_component_template/${templateName}@mappings`, + path: `/_component_template/${templateName}@package`, }, { meta: true, } )); - // The mappings override provided in the package is set in the mappings component template + // The mappings override provided in the package is set in the package component template expect(body.component_templates[0].component_template.template.mappings.dynamic).to.be(false); - ({ body } = await es.transport.request( - { - method: 'GET', - path: `/_component_template/${templateName}@settings`, - }, - { meta: true } - )); - - // The settings override provided in the package is set in the settings component template + // The settings override provided in the package is set in the package component template expect( body.component_templates[0].component_template.template.settings.index.lifecycle.name ).to.be('reference'); @@ -122,11 +113,7 @@ export default function (providerContext: FtrProviderContext) { // body: indexTemplate, // I *think* this should work, but it doesn't body: { index_patterns: [`${templateName}-*`], - composed_of: [ - `${templateName}@mappings`, - `${templateName}@settings`, - `${templateName}@custom`, - ], + composed_of: [`${templateName}@package`, `${templateName}@custom`], }, }, { meta: true } diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts index 4212ca46fc3c9..34cebed5b5d5a 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts @@ -91,29 +91,17 @@ export default function (providerContext: FtrProviderContext) { expect(resMetricsTemplate.statusCode).equal(404); }); it('should have uninstalled the component templates', async function () { - const resMappings = await es.transport.request( + const resPackage = await es.transport.request( { method: 'GET', - path: `/_component_template/${logsTemplateName}@mappings`, + path: `/_component_template/${logsTemplateName}@package`, }, { ignore: [404], meta: true, } ); - expect(resMappings.statusCode).equal(404); - - const resSettings = await es.transport.request( - { - method: 'GET', - path: `/_component_template/${logsTemplateName}@settings`, - }, - { - ignore: [404], - meta: true, - } - ); - expect(resSettings.statusCode).equal(404); + expect(resPackage.statusCode).equal(404); const resUserSettings = await es.transport.request( { @@ -382,22 +370,15 @@ const expectAssetsInstalled = ({ expect(res.statusCode).equal(200); }); it('should have installed the component templates', async function () { - const resMappings = await es.transport.request( + const resPackage = await es.transport.request( { method: 'GET', - path: `/_component_template/${logsTemplateName}@mappings`, + path: `/_component_template/${logsTemplateName}@package`, }, { meta: true } ); - expect(resMappings.statusCode).equal(200); - const resSettings = await es.transport.request( - { - method: 'GET', - path: `/_component_template/${logsTemplateName}@settings`, - }, - { meta: true } - ); - expect(resSettings.statusCode).equal(200); + expect(resPackage.statusCode).equal(200); + const resUserSettings = await es.transport.request( { method: 'GET', @@ -565,11 +546,7 @@ const expectAssetsInstalled = ({ installed_kibana_space_id: 'default', installed_es: [ { - id: 'logs-all_assets.test_logs@mappings', - type: 'component_template', - }, - { - id: 'logs-all_assets.test_logs@settings', + id: 'logs-all_assets.test_logs@package', type: 'component_template', }, { @@ -577,11 +554,7 @@ const expectAssetsInstalled = ({ type: 'component_template', }, { - id: 'metrics-all_assets.test_metrics@mappings', - type: 'component_template', - }, - { - id: 'metrics-all_assets.test_metrics@settings', + id: 'metrics-all_assets.test_metrics@package', type: 'component_template', }, { diff --git a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts index 7a69d5635f9ac..b73ca9537990c 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts @@ -122,16 +122,16 @@ export default function (providerContext: FtrProviderContext) { }); }); it('should have populated the new component template with the correct mapping', async () => { - const resMappings = await es.transport.request( + const resPackage = await es.transport.request( { method: 'GET', - path: `/_component_template/${logsTemplateName2}@mappings`, + path: `/_component_template/${logsTemplateName2}@package`, }, { meta: true } ); - expect(resMappings.statusCode).equal(200); + expect(resPackage.statusCode).equal(200); expect( - resMappings.body.component_templates[0].component_template.template.mappings.properties + resPackage.body.component_templates[0].component_template.template.mappings.properties ).eql({ '@timestamp': { type: 'date', @@ -204,24 +204,31 @@ export default function (providerContext: FtrProviderContext) { expect(resPipeline2.statusCode).equal(404); }); it('should have updated the logs component templates', async function () { - const resMappings = await es.transport.request( + const resPackage = await es.transport.request( { method: 'GET', - path: `/_component_template/${logsTemplateName}@mappings`, + path: `/_component_template/${logsTemplateName}@package`, }, { meta: true } ); - expect(resMappings.statusCode).equal(200); - expect(resMappings.body.component_templates[0].component_template.template.settings).eql({ + expect(resPackage.statusCode).equal(200); + expect(resPackage.body.component_templates[0].component_template.template.settings).eql({ index: { + codec: 'best_compression', + lifecycle: { + name: 'reference2', + }, mapping: { total_fields: { limit: '10000', }, }, + query: { + default_field: ['logs_test_name', 'new_field_name'], + }, }, }); - expect(resMappings.body.component_templates[0].component_template.template.mappings).eql({ + expect(resPackage.body.component_templates[0].component_template.template.mappings).eql({ dynamic: true, properties: { '@timestamp': { @@ -249,23 +256,7 @@ export default function (providerContext: FtrProviderContext) { }, }, }); - const resSettings = await es.transport.request( - { - method: 'GET', - path: `/_component_template/${logsTemplateName}@settings`, - }, - { meta: true } - ); - expect(resSettings.statusCode).equal(200); - expect(resSettings.body.component_templates[0].component_template.template.settings).eql({ - index: { - lifecycle: { name: 'reference2' }, - codec: 'best_compression', - query: { - default_field: ['logs_test_name', 'new_field_name'], - }, - }, - }); + const resUserSettings = await es.transport.request( { method: 'GET', @@ -295,16 +286,16 @@ export default function (providerContext: FtrProviderContext) { }); }); it('should have updated the metrics mapping component template', async function () { - const resMappings = await es.transport.request( + const resPackage = await es.transport.request( { method: 'GET', - path: `/_component_template/${metricsTemplateName}@mappings`, + path: `/_component_template/${metricsTemplateName}@package`, }, { meta: true } ); - expect(resMappings.statusCode).equal(200); + expect(resPackage.statusCode).equal(200); expect( - resMappings.body.component_templates[0].component_template.template.mappings.properties + resPackage.body.component_templates[0].component_template.template.mappings.properties ).eql({ '@timestamp': { type: 'date', @@ -432,11 +423,7 @@ export default function (providerContext: FtrProviderContext) { type: 'index_template', }, { - id: 'logs-all_assets.test_logs@mappings', - type: 'component_template', - }, - { - id: 'logs-all_assets.test_logs@settings', + id: 'logs-all_assets.test_logs@package', type: 'component_template', }, { @@ -448,11 +435,7 @@ export default function (providerContext: FtrProviderContext) { type: 'index_template', }, { - id: 'logs-all_assets.test_logs2@mappings', - type: 'component_template', - }, - { - id: 'logs-all_assets.test_logs2@settings', + id: 'logs-all_assets.test_logs2@package', type: 'component_template', }, { @@ -464,11 +447,7 @@ export default function (providerContext: FtrProviderContext) { type: 'index_template', }, { - id: 'metrics-all_assets.test_metrics@mappings', - type: 'component_template', - }, - { - id: 'metrics-all_assets.test_metrics@settings', + id: 'metrics-all_assets.test_metrics@package', type: 'component_template', }, { From 2e4274ca88c86a6a49934602f1ebb29913397ab0 Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Tue, 29 Mar 2022 11:10:35 -0400 Subject: [PATCH 28/31] [CI] Move hourly CI tasks to on merge (#128505) --- .buildkite/pipelines/hourly.yml | 218 -------------- .buildkite/pipelines/on_merge.yml | 216 +++++++++++++- .buildkite/pipelines/pull_request/base.yml | 7 + .../scripts/lifecycle/ci_stats_ready.js | 23 ++ .buildkite/scripts/steps/build_api_docs.sh | 8 + .buildkite/scripts/steps/checks.sh | 2 +- .../scripts/steps/checks/check_types.sh | 9 + .../type_check_plugin_public_api_docs.sh | 40 --- .buildkite/scripts/steps/ci_stats_ready.sh | 7 + .../steps/on_merge_build_and_metrics.sh | 2 + .buildkite/yarn.lock | 282 ++++++++---------- 11 files changed, 388 insertions(+), 426 deletions(-) delete mode 100644 .buildkite/pipelines/hourly.yml create mode 100644 .buildkite/scripts/lifecycle/ci_stats_ready.js create mode 100755 .buildkite/scripts/steps/build_api_docs.sh create mode 100755 .buildkite/scripts/steps/checks/check_types.sh delete mode 100755 .buildkite/scripts/steps/checks/type_check_plugin_public_api_docs.sh create mode 100755 .buildkite/scripts/steps/ci_stats_ready.sh diff --git a/.buildkite/pipelines/hourly.yml b/.buildkite/pipelines/hourly.yml deleted file mode 100644 index 1335866675564..0000000000000 --- a/.buildkite/pipelines/hourly.yml +++ /dev/null @@ -1,218 +0,0 @@ -steps: - - command: .buildkite/scripts/lifecycle/pre_build.sh - label: Pre-Build - timeout_in_minutes: 10 - agents: - queue: kibana-default - - - wait - - - command: .buildkite/scripts/steps/build_kibana.sh - label: Build Kibana Distribution and Plugins - agents: - queue: c2-16 - key: build - if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''" - timeout_in_minutes: 60 - - - command: .buildkite/scripts/steps/functional/xpack_cigroup.sh - label: 'Default CI Group' - parallelism: 27 - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 250 - key: default-cigroup - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: CI_GROUP=Docker .buildkite/scripts/steps/functional/xpack_cigroup.sh - label: 'Docker CI Group' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - key: default-cigroup-docker - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_cigroup.sh - label: 'OSS CI Group' - parallelism: 11 - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - key: oss-cigroup - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_accessibility.sh - label: 'OSS Accessibility Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_accessibility.sh - label: 'Default Accessibility Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_firefox.sh - label: 'OSS Firefox Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_firefox.sh - label: 'Default Firefox Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/oss_misc.sh - label: 'OSS Misc Functional Tests' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh - label: 'Saved Object Field Metrics' - agents: - queue: n2-4-spot - depends_on: build - timeout_in_minutes: 120 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - exit_status: '*' - limit: 1 - - - command: .buildkite/scripts/steps/test/jest.sh - label: 'Jest Tests' - parallelism: 8 - agents: - queue: n2-4-spot - timeout_in_minutes: 90 - key: jest - retry: - automatic: - - exit_status: '-1' - limit: 3 - - - command: .buildkite/scripts/steps/test/jest_integration.sh - label: 'Jest Integration Tests' - parallelism: 3 - agents: - queue: n2-4-spot - timeout_in_minutes: 120 - key: jest-integration - retry: - automatic: - - exit_status: '-1' - limit: 3 - - - command: .buildkite/scripts/steps/test/api_integration.sh - label: 'API Integration Tests' - agents: - queue: n2-2-spot - timeout_in_minutes: 120 - key: api-integration - retry: - automatic: - - exit_status: '-1' - limit: 3 - - - command: .buildkite/scripts/steps/lint.sh - label: 'Linting' - agents: - queue: n2-2-spot - key: linting - timeout_in_minutes: 90 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - - command: .buildkite/scripts/steps/lint_with_types.sh - label: 'Linting (with types)' - agents: - queue: c2-16 - key: linting_with_types - timeout_in_minutes: 90 - - - command: .buildkite/scripts/steps/checks.sh - label: 'Checks' - agents: - queue: c2-8 - key: checks - timeout_in_minutes: 120 - - - command: .buildkite/scripts/steps/storybooks/build_and_upload.sh - label: 'Build Storybooks' - agents: - queue: n2-4-spot - key: storybooks - timeout_in_minutes: 60 - retry: - automatic: - - exit_status: '-1' - limit: 3 - - - wait: ~ - continue_on_failure: true - - - command: .buildkite/scripts/lifecycle/post_build.sh - label: Post-Build - timeout_in_minutes: 10 - agents: - queue: kibana-default diff --git a/.buildkite/pipelines/on_merge.yml b/.buildkite/pipelines/on_merge.yml index c6acb48b3e212..a11f566b06093 100644 --- a/.buildkite/pipelines/on_merge.yml +++ b/.buildkite/pipelines/on_merge.yml @@ -7,13 +7,18 @@ steps: timeout_in_minutes: 10 agents: queue: kibana-default + retry: + automatic: + - exit_status: '*' + limit: 1 - wait - command: .buildkite/scripts/steps/on_merge_build_and_metrics.sh - label: Default Build and Metrics + label: Build Kibana Distribution and Plugins agents: - queue: c2-8 + queue: c2-16 + key: build timeout_in_minutes: 60 retry: automatic: @@ -22,6 +27,7 @@ steps: - command: .buildkite/scripts/steps/on_merge_ts_refs_api_docs.sh label: Build TS Refs and Check Public API Docs + key: public-api-docs agents: queue: c2-4 timeout_in_minutes: 80 @@ -30,6 +36,212 @@ steps: - exit_status: '*' limit: 1 + - command: .buildkite/scripts/steps/ci_stats_ready.sh + label: Mark CI Stats as ready + agents: + queue: kibana-default + timeout_in_minutes: 10 + depends_on: + - build + - public-api-docs + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/xpack_cigroup.sh + label: 'Default CI Group' + parallelism: 27 + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 250 + key: default-cigroup + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: CI_GROUP=Docker .buildkite/scripts/steps/functional/xpack_cigroup.sh + label: 'Docker CI Group' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + key: default-cigroup-docker + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/oss_cigroup.sh + label: 'OSS CI Group' + parallelism: 11 + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + key: oss-cigroup + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/oss_accessibility.sh + label: 'OSS Accessibility Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/xpack_accessibility.sh + label: 'Default Accessibility Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/oss_firefox.sh + label: 'OSS Firefox Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/xpack_firefox.sh + label: 'Default Firefox Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/oss_misc.sh + label: 'OSS Misc Functional Tests' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/xpack_saved_object_field_metrics.sh + label: 'Saved Object Field Metrics' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/test/jest.sh + label: 'Jest Tests' + parallelism: 8 + agents: + queue: n2-4-spot + timeout_in_minutes: 90 + key: jest + retry: + automatic: + - exit_status: '-1' + limit: 3 + + - command: .buildkite/scripts/steps/test/jest_integration.sh + label: 'Jest Integration Tests' + parallelism: 3 + agents: + queue: n2-4-spot + timeout_in_minutes: 120 + key: jest-integration + retry: + automatic: + - exit_status: '-1' + limit: 3 + + - command: .buildkite/scripts/steps/test/api_integration.sh + label: 'API Integration Tests' + agents: + queue: n2-2-spot + timeout_in_minutes: 120 + key: api-integration + retry: + automatic: + - exit_status: '-1' + limit: 3 + + - command: .buildkite/scripts/steps/lint.sh + label: 'Linting' + agents: + queue: n2-2-spot + key: linting + timeout_in_minutes: 90 + retry: + automatic: + - exit_status: '-1' + limit: 3 + + - command: .buildkite/scripts/steps/lint_with_types.sh + label: 'Linting (with types)' + agents: + queue: c2-16 + key: linting_with_types + timeout_in_minutes: 90 + + - command: .buildkite/scripts/steps/checks.sh + label: 'Checks' + agents: + queue: c2-8 + key: checks + timeout_in_minutes: 120 + + - command: .buildkite/scripts/steps/storybooks/build_and_upload.sh + label: 'Build Storybooks' + agents: + queue: n2-4-spot + key: storybooks + timeout_in_minutes: 60 + retry: + automatic: + - exit_status: '-1' + limit: 3 + - wait: ~ continue_on_failure: true diff --git a/.buildkite/pipelines/pull_request/base.yml b/.buildkite/pipelines/pull_request/base.yml index 4aa9a7a49fe23..eaad8ca875545 100644 --- a/.buildkite/pipelines/pull_request/base.yml +++ b/.buildkite/pipelines/pull_request/base.yml @@ -170,6 +170,13 @@ steps: key: storybooks timeout_in_minutes: 60 + - command: .buildkite/scripts/steps/build_api_docs.sh + label: 'Build API Docs' + agents: + queue: n2-4 + key: build_api_docs + timeout_in_minutes: 60 + - command: .buildkite/scripts/steps/webpack_bundle_analyzer/build_and_upload.sh label: 'Build Webpack Bundle Analyzer reports' agents: diff --git a/.buildkite/scripts/lifecycle/ci_stats_ready.js b/.buildkite/scripts/lifecycle/ci_stats_ready.js new file mode 100644 index 0000000000000..98b03a56d0023 --- /dev/null +++ b/.buildkite/scripts/lifecycle/ci_stats_ready.js @@ -0,0 +1,23 @@ +/* + * 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 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +// eslint-disable-next-line import/no-unresolved +const { CiStats } = require('kibana-buildkite-library'); + +(async () => { + try { + await CiStats.onMetricsViable(); + } catch (ex) { + console.error('CI Stats Error', ex.message); + if (ex.response) { + console.error('HTTP Error Response Status', ex.response.status); + console.error('HTTP Error Response Body', ex.response.data); + } + process.exit(1); + } +})(); diff --git a/.buildkite/scripts/steps/build_api_docs.sh b/.buildkite/scripts/steps/build_api_docs.sh new file mode 100755 index 0000000000000..2f63d6efa0941 --- /dev/null +++ b/.buildkite/scripts/steps/build_api_docs.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash + +set -euo pipefail + +.buildkite/scripts/bootstrap.sh + +echo "--- Build API Docs" +node --max-old-space-size=12000 scripts/build_api_docs diff --git a/.buildkite/scripts/steps/checks.sh b/.buildkite/scripts/steps/checks.sh index bde9e82a4d1e6..cae019150b626 100755 --- a/.buildkite/scripts/steps/checks.sh +++ b/.buildkite/scripts/steps/checks.sh @@ -13,7 +13,7 @@ export DISABLE_BOOTSTRAP_VALIDATION=false .buildkite/scripts/steps/checks/doc_api_changes.sh .buildkite/scripts/steps/checks/kbn_pm_dist.sh .buildkite/scripts/steps/checks/plugin_list_docs.sh -.buildkite/scripts/steps/checks/type_check_plugin_public_api_docs.sh +.buildkite/scripts/steps/checks/check_types.sh .buildkite/scripts/steps/checks/bundle_limits.sh .buildkite/scripts/steps/checks/i18n.sh .buildkite/scripts/steps/checks/file_casing.sh diff --git a/.buildkite/scripts/steps/checks/check_types.sh b/.buildkite/scripts/steps/checks/check_types.sh new file mode 100755 index 0000000000000..3b649a73e8060 --- /dev/null +++ b/.buildkite/scripts/steps/checks/check_types.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/common/util.sh + +echo --- Check Types +checks-reporter-with-killswitch "Check Types" \ + node scripts/type_check diff --git a/.buildkite/scripts/steps/checks/type_check_plugin_public_api_docs.sh b/.buildkite/scripts/steps/checks/type_check_plugin_public_api_docs.sh deleted file mode 100755 index e2a4bd9d9d427..0000000000000 --- a/.buildkite/scripts/steps/checks/type_check_plugin_public_api_docs.sh +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env bash - -set -euo pipefail - -source .buildkite/scripts/common/util.sh - -echo --- Build TS Refs -checks-reporter-with-killswitch "Build TS Refs" \ - node scripts/build_ts_refs \ - --clean \ - --no-cache \ - --force - -set +e; -echo "--- running check types and build api docs in parallel"; - -checks-reporter-with-killswitch "Check Types" \ - node scripts/type_check &> target/check_types.log & -check_types_pid=$! - -node --max-old-space-size=12000 scripts/build_api_docs &> target/build_api_docs.log & -api_docs_pid=$! - -wait $check_types_pid -check_types_exit=$? - -wait $api_docs_pid -api_docs_exit=$? - -echo --- Check Types -cat target/check_types.log -if [[ "$check_types_exit" != "0" ]]; then echo "^^^ +++"; fi - -echo --- Building api docs -cat target/build_api_docs.log -if [[ "$api_docs_exit" != "0" ]]; then echo "^^^ +++"; fi - -if [[ "${api_docs_exit}${check_types_exit}" != "00" ]]; then - exit 1 -fi diff --git a/.buildkite/scripts/steps/ci_stats_ready.sh b/.buildkite/scripts/steps/ci_stats_ready.sh new file mode 100755 index 0000000000000..92ea6a70fd779 --- /dev/null +++ b/.buildkite/scripts/steps/ci_stats_ready.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/common/util.sh + +node .buildkite/scripts/lifecycle/ci_stats_ready.js diff --git a/.buildkite/scripts/steps/on_merge_build_and_metrics.sh b/.buildkite/scripts/steps/on_merge_build_and_metrics.sh index 1f1e492f87bec..fb05bb99b0c54 100755 --- a/.buildkite/scripts/steps/on_merge_build_and_metrics.sh +++ b/.buildkite/scripts/steps/on_merge_build_and_metrics.sh @@ -4,5 +4,7 @@ set -euo pipefail .buildkite/scripts/bootstrap.sh .buildkite/scripts/build_kibana.sh +.buildkite/scripts/build_kibana_plugins.sh +.buildkite/scripts/post_build_kibana_plugins.sh .buildkite/scripts/post_build_kibana.sh .buildkite/scripts/saved_object_field_metrics.sh diff --git a/.buildkite/yarn.lock b/.buildkite/yarn.lock index 2c3ce924b22ea..c2d6928d30c5a 100644 --- a/.buildkite/yarn.lock +++ b/.buildkite/yarn.lock @@ -3,226 +3,178 @@ "@octokit/auth-token@^2.4.4": - version "2.4.4" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.4.tgz#ee31c69b01d0378c12fd3ffe406030f3d94d3b56" - integrity sha512-LNfGu3Ro9uFAYh10MUZVaT7X2CnNm2C8IDQmabx+3DygYIQjs9FwzFAHN/0t6mu5HEPhxcb1XOuxdpY82vCg2Q== + "integrity" "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==" + "resolved" "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz" + "version" "2.5.0" dependencies: - "@octokit/types" "^6.0.0" + "@octokit/types" "^6.0.3" -"@octokit/core@^3.5.1": - version "3.5.1" - resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.5.1.tgz#8601ceeb1ec0e1b1b8217b960a413ed8e947809b" - integrity sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw== +"@octokit/core@^3.5.1", "@octokit/core@>=2", "@octokit/core@>=3": + "integrity" "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==" + "resolved" "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz" + "version" "3.5.1" dependencies: "@octokit/auth-token" "^2.4.4" "@octokit/graphql" "^4.5.8" "@octokit/request" "^5.6.0" "@octokit/request-error" "^2.0.5" "@octokit/types" "^6.0.3" - before-after-hook "^2.2.0" - universal-user-agent "^6.0.0" + "before-after-hook" "^2.2.0" + "universal-user-agent" "^6.0.0" "@octokit/endpoint@^6.0.1": - version "6.0.9" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.9.tgz#c6a772e024202b1bd19ab69f90e0536a2598b13e" - integrity sha512-3VPLbcCuqji4IFTclNUtGdp9v7g+nspWdiCUbK3+iPMjJCZ6LEhn1ts626bWLOn0GiDb6j+uqGvPpqLnY7pBgw== + "integrity" "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==" + "resolved" "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz" + "version" "6.0.12" dependencies: - "@octokit/types" "^5.0.0" - is-plain-object "^5.0.0" - universal-user-agent "^6.0.0" + "@octokit/types" "^6.0.3" + "is-plain-object" "^5.0.0" + "universal-user-agent" "^6.0.0" "@octokit/graphql@^4.5.8": - version "4.5.8" - resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.5.8.tgz#d42373633c3015d0eafce64a8ce196be167fdd9b" - integrity sha512-WnCtNXWOrupfPJgXe+vSmprZJUr0VIu14G58PMlkWGj3cH+KLZEfKMmbUQ6C3Wwx6fdhzVW1CD5RTnBdUHxhhA== + "integrity" "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==" + "resolved" "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz" + "version" "4.8.0" dependencies: - "@octokit/request" "^5.3.0" - "@octokit/types" "^6.0.0" - universal-user-agent "^6.0.0" + "@octokit/request" "^5.6.0" + "@octokit/types" "^6.0.3" + "universal-user-agent" "^6.0.0" "@octokit/openapi-types@^11.2.0": - version "11.2.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-11.2.0.tgz#b38d7fc3736d52a1e96b230c1ccd4a58a2f400a6" - integrity sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA== - -"@octokit/openapi-types@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-2.2.0.tgz#123e0438a0bc718ccdac3b5a2e69b3dd00daa85b" - integrity sha512-274lNUDonw10kT8wHg8fCcUc1ZjZHbWv0/TbAwb0ojhBQqZYc1cQ/4yqTVTtPMDeZ//g7xVEYe/s3vURkRghPg== + "integrity" "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" + "resolved" "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz" + "version" "11.2.0" "@octokit/plugin-paginate-rest@^2.16.8": - version "2.17.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz#32e9c7cab2a374421d3d0de239102287d791bce7" - integrity sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw== + "integrity" "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==" + "resolved" "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz" + "version" "2.17.0" dependencies: "@octokit/types" "^6.34.0" "@octokit/plugin-request-log@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz#5e50ed7083a613816b1e4a28aeec5fb7f1462e85" - integrity sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA== + "integrity" "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==" + "resolved" "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz" + "version" "1.0.4" "@octokit/plugin-rest-endpoint-methods@^5.12.0": - version "5.13.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz#8c46109021a3412233f6f50d28786f8e552427ba" - integrity sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA== + "integrity" "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==" + "resolved" "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz" + "version" "5.13.0" dependencies: "@octokit/types" "^6.34.0" - deprecation "^2.3.1" - -"@octokit/request-error@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.3.tgz#b51b200052bf483f6fa56c9e7e3aa51ead36ecd8" - integrity sha512-GgD5z8Btm301i2zfvJLk/mkhvGCdjQ7wT8xF9ov5noQY8WbKZDH9cOBqXzoeKd1mLr1xH2FwbtGso135zGBgTA== - dependencies: - "@octokit/types" "^5.0.1" - deprecation "^2.0.0" - once "^1.4.0" + "deprecation" "^2.3.1" "@octokit/request-error@^2.0.5", "@octokit/request-error@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.1.0.tgz#9e150357831bfc788d13a4fd4b1913d60c74d677" - integrity sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg== + "integrity" "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==" + "resolved" "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz" + "version" "2.1.0" dependencies: "@octokit/types" "^6.0.3" - deprecation "^2.0.0" - once "^1.4.0" - -"@octokit/request@^5.3.0": - version "5.4.12" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.12.tgz#b04826fa934670c56b135a81447be2c1723a2ffc" - integrity sha512-MvWYdxengUWTGFpfpefBBpVmmEYfkwMoxonIB3sUGp5rhdgwjXL1ejo6JbgzG/QD9B/NYt/9cJX1pxXeSIUCkg== - dependencies: - "@octokit/endpoint" "^6.0.1" - "@octokit/request-error" "^2.0.0" - "@octokit/types" "^6.0.3" - deprecation "^2.0.0" - is-plain-object "^5.0.0" - node-fetch "^2.6.1" - once "^1.4.0" - universal-user-agent "^6.0.0" + "deprecation" "^2.0.0" + "once" "^1.4.0" "@octokit/request@^5.6.0": - version "5.6.2" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.6.2.tgz#1aa74d5da7b9e04ac60ef232edd9a7438dcf32d8" - integrity sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA== + "integrity" "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==" + "resolved" "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz" + "version" "5.6.2" dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.1.0" "@octokit/types" "^6.16.1" - is-plain-object "^5.0.0" - node-fetch "^2.6.1" - universal-user-agent "^6.0.0" + "is-plain-object" "^5.0.0" + "node-fetch" "^2.6.1" + "universal-user-agent" "^6.0.0" "@octokit/rest@^18.10.0": - version "18.12.0" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.12.0.tgz#f06bc4952fc87130308d810ca9d00e79f6988881" - integrity sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q== + "integrity" "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==" + "resolved" "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz" + "version" "18.12.0" dependencies: "@octokit/core" "^3.5.1" "@octokit/plugin-paginate-rest" "^2.16.8" "@octokit/plugin-request-log" "^1.0.4" "@octokit/plugin-rest-endpoint-methods" "^5.12.0" -"@octokit/types@^5.0.0", "@octokit/types@^5.0.1": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" - integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== +"@octokit/types@^6.0.3", "@octokit/types@^6.16.1", "@octokit/types@^6.34.0": + "integrity" "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==" + "resolved" "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz" + "version" "6.34.0" dependencies: - "@types/node" ">= 8" + "@octokit/openapi-types" "^11.2.0" -"@octokit/types@^6.0.0", "@octokit/types@^6.0.3": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.2.1.tgz#7f881fe44475ab1825776a4a59ca1ae082ed1043" - integrity sha512-jHs9OECOiZxuEzxMZcXmqrEO8GYraHF+UzNVH2ACYh8e/Y7YoT+hUf9ldvVd6zIvWv4p3NdxbQ0xx3ku5BnSiA== +"axios@^0.21.4": + "integrity" "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==" + "resolved" "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz" + "version" "0.21.4" dependencies: - "@octokit/openapi-types" "^2.2.0" - "@types/node" ">= 8" + "follow-redirects" "^1.14.0" -"@octokit/types@^6.16.1", "@octokit/types@^6.34.0": - version "6.34.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.34.0.tgz#c6021333334d1ecfb5d370a8798162ddf1ae8218" - integrity sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw== - dependencies: - "@octokit/openapi-types" "^11.2.0" +"before-after-hook@^2.2.0": + "integrity" "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" + "resolved" "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz" + "version" "2.2.2" -"@types/node@>= 8": - version "16.10.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.10.2.tgz#5764ca9aa94470adb4e1185fe2e9f19458992b2e" - integrity sha512-zCclL4/rx+W5SQTzFs9wyvvyCwoK9QtBpratqz2IYJ3O8Umrn0m3nsTv0wQBk9sRGpvUe9CwPDrQFB10f1FIjQ== +"deprecation@^2.0.0", "deprecation@^2.3.1": + "integrity" "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + "resolved" "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz" + "version" "2.3.1" -axios@^0.21.4: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== - dependencies: - follow-redirects "^1.14.0" - -before-after-hook@^2.2.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.2.tgz#a6e8ca41028d90ee2c24222f201c90956091613e" - integrity sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ== - -deprecation@^2.0.0, deprecation@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" - integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== - -follow-redirects@^1.14.0: - version "1.14.3" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.3.tgz#6ada78118d8d24caee595595accdc0ac6abd022e" - integrity sha512-3MkHxknWMUtb23apkgz/83fDoe+y+qr0TdgacGIA7bew+QLBo3vdgEN2xEsuXNivpFy4CyDhBBZnNZOtalmenw== - -is-plain-object@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" - integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== - -kibana-buildkite-library@elastic/kibana-buildkite-library: - version "1.0.0" - resolved "https://codeload.github.com/elastic/kibana-buildkite-library/tar.gz/f67122968ea54ba14036b55c9f99906d96a3733d" +"follow-redirects@^1.14.0": + "integrity" "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" + "resolved" "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz" + "version" "1.14.5" + +"is-plain-object@^5.0.0": + "integrity" "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + "resolved" "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz" + "version" "5.0.0" + +"kibana-buildkite-library@github:elastic/kibana-buildkite-library": + "resolved" "git+ssh://git@github.com/elastic/kibana-buildkite-library.git#ccf5b824c4294d1fdf3569d32218d3bdb0958121" + "version" "1.0.0" dependencies: "@octokit/rest" "^18.10.0" - axios "^0.21.4" + "axios" "^0.21.4" -node-fetch@^2.6.1: - version "2.6.5" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.5.tgz#42735537d7f080a7e5f78b6c549b7146be1742fd" - integrity sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ== +"node-fetch@^2.6.1": + "integrity" "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==" + "resolved" "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz" + "version" "2.6.6" dependencies: - whatwg-url "^5.0.0" + "whatwg-url" "^5.0.0" -once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= +"once@^1.4.0": + "integrity" "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=" + "resolved" "https://registry.npmjs.org/once/-/once-1.4.0.tgz" + "version" "1.4.0" dependencies: - wrappy "1" - -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - -universal-user-agent@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" - integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== - -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + "wrappy" "1" + +"tr46@~0.0.3": + "integrity" "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + "resolved" "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz" + "version" "0.0.3" + +"universal-user-agent@^6.0.0": + "integrity" "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + "resolved" "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz" + "version" "6.0.0" + +"webidl-conversions@^3.0.0": + "integrity" "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + "resolved" "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz" + "version" "3.0.1" + +"whatwg-url@^5.0.0": + "integrity" "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=" + "resolved" "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz" + "version" "5.0.0" dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" + "tr46" "~0.0.3" + "webidl-conversions" "^3.0.0" -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +"wrappy@1": + "integrity" "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "resolved" "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz" + "version" "1.0.2" From 437adb58805e3b524851de4b9727d7e3951c3f4c Mon Sep 17 00:00:00 2001 From: Mat Schaffer Date: Wed, 30 Mar 2022 00:13:35 +0900 Subject: [PATCH 29/31] [Stack Monitoring] Rename "APM & Fleet Server" to "Integrations Server" (#128574) --- .../dev_docs/how_to/running_components_from_source.md | 2 +- .../monitoring/public/components/apm/apm_metrics.tsx | 6 ++---- .../public/components/cluster/overview/apm_panel.js | 8 ++++---- x-pack/plugins/monitoring/public/lib/apm_agent.ts | 5 +++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/monitoring/dev_docs/how_to/running_components_from_source.md b/x-pack/plugins/monitoring/dev_docs/how_to/running_components_from_source.md index fcb3bae429e7c..2008d913238f5 100644 --- a/x-pack/plugins/monitoring/dev_docs/how_to/running_components_from_source.md +++ b/x-pack/plugins/monitoring/dev_docs/how_to/running_components_from_source.md @@ -323,7 +323,7 @@ And start it with: ./apm-server -c apm-server.source.yml -e -d "*" ``` -Note that on cloud the APM server section will show up as "APM & Fleet Server", but the code paths are the same. +Note that on cloud the APM server section will show up as "Integrations Server" (previously "APM & Fleet"), but the code paths are the same. ## Logstash diff --git a/x-pack/plugins/monitoring/public/components/apm/apm_metrics.tsx b/x-pack/plugins/monitoring/public/components/apm/apm_metrics.tsx index c4e5c51856013..2f6eea57b6090 100644 --- a/x-pack/plugins/monitoring/public/components/apm/apm_metrics.tsx +++ b/x-pack/plugins/monitoring/public/components/apm/apm_metrics.tsx @@ -22,8 +22,6 @@ import { FormattedMessage } from '@kbn/i18n-react'; // @ts-ignore could not find declaration file import { MonitoringTimeseriesContainer } from '../chart'; -// @ts-ignore could not find declaration file -import { Status } from './instance/status'; import { checkAgentTypeMetric } from '../../lib/apm_agent'; interface TitleType { @@ -63,12 +61,12 @@ const getHeading = (isFleetTypeMetric: boolean) => { const titles: TitleType = {}; if (isFleetTypeMetric) { titles.title = i18n.translate('xpack.monitoring.apm.metrics.topCharts.agentTitle', { - defaultMessage: 'APM & Fleet Server - Resource Usage', + defaultMessage: 'Integrations Server - Resource Usage', }); titles.heading = ( ); return titles; diff --git a/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js b/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js index 2a2e6719ab268..24b1d508bb3c1 100644 --- a/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js +++ b/x-pack/plugins/monitoring/public/components/cluster/overview/apm_panel.js @@ -39,14 +39,14 @@ const getServerTitle = (isFleetTypeMetric, total) => { linkLabel.link = ( ); linkLabel.aria = i18n.translate( 'xpack.monitoring.cluster.overview.apmPanel.instancesAndFleetsTotalLinkAriaLabel', { - defaultMessage: 'APM and Fleet server instances: {apmsTotal}', + defaultMessage: 'Integrations server instances: {apmsTotal}', values: { apmsTotal }, } ); @@ -73,7 +73,7 @@ const getServerTitle = (isFleetTypeMetric, total) => { const getOverviewTitle = (isFleetTypeMetric) => { if (isFleetTypeMetric) { return i18n.translate('xpack.monitoring.cluster.overview.apmPanel.overviewFleetLinkLabel', { - defaultMessage: 'APM & Fleet server overview', + defaultMessage: 'Integrations server overview', }); } return i18n.translate('xpack.monitoring.cluster.overview.apmPanel.overviewLinkLabel', { @@ -84,7 +84,7 @@ const getOverviewTitle = (isFleetTypeMetric) => { const getHeadingTitle = (isFleetTypeMetric) => { if (isFleetTypeMetric) { return i18n.translate('xpack.monitoring.cluster.overview.apmPanel.apmFleetTitle', { - defaultMessage: 'APM & Fleet server', + defaultMessage: 'Integrations server', }); } return i18n.translate('xpack.monitoring.cluster.overview.apmPanel.apmTitle', { diff --git a/x-pack/plugins/monitoring/public/lib/apm_agent.ts b/x-pack/plugins/monitoring/public/lib/apm_agent.ts index 09419b7c91bf0..bf992cc560d1e 100644 --- a/x-pack/plugins/monitoring/public/lib/apm_agent.ts +++ b/x-pack/plugins/monitoring/public/lib/apm_agent.ts @@ -8,8 +8,9 @@ import { Legacy } from '../legacy_shims'; /** - * Possible temporary work arround to establish if APM might also be monitoring fleet: - * https://github.com/elastic/kibana/pull/95129/files#r604815886 + * Checks if on cloud and >= 7.13 + * In this configuration APM server should be running within elastic agent. + * See https://github.com/elastic/kibana/issues/97879 for details. */ export const checkAgentTypeMetric = (versions?: string[]) => { if (!Legacy.shims.isCloud || !versions) { From 5efb4b1cf62be06ce7a24361050f03208fc0bfb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20Zolt=C3=A1n=20Szab=C3=B3?= Date: Tue, 29 Mar 2022 17:22:27 +0200 Subject: [PATCH 30/31] [DOCS] Adds GET case API docs (#128606) --- docs/api/cases.asciidoc | 4 +- docs/api/cases/cases-api-get-case.asciidoc | 100 +++++++++++++++++++++ 2 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 docs/api/cases/cases-api-get-case.asciidoc diff --git a/docs/api/cases.asciidoc b/docs/api/cases.asciidoc index 5aa837d35676e..273f3a0b51cc2 100644 --- a/docs/api/cases.asciidoc +++ b/docs/api/cases.asciidoc @@ -14,7 +14,7 @@ these APIs: * <> * {security-guide}/cases-api-get-case-activity.html[Get all case activity] * {security-guide}/cases-api-get-all-case-comments.html[Get all case comments] -* {security-guide}/cases-api-get-case.html[Get case] +* <> * {security-guide}/cases-api-get-comment.html[Get comment] * {security-guide}/cases-get-connector.html[Get current connector] * {security-guide}/cases-api-get-reporters.html[Get reporters] @@ -34,5 +34,7 @@ include::cases/cases-api-delete-comments.asciidoc[leveloffset=+1] //FIND include::cases/cases-api-find-cases.asciidoc[leveloffset=+1] include::cases/cases-api-find-connectors.asciidoc[leveloffset=+1] +//GET +include::cases/cases-api-get-case.asciidoc[leveloffset=+1] //UPDATE include::cases/cases-api-update.asciidoc[leveloffset=+1] diff --git a/docs/api/cases/cases-api-get-case.asciidoc b/docs/api/cases/cases-api-get-case.asciidoc new file mode 100644 index 0000000000000..6bd255f6f8326 --- /dev/null +++ b/docs/api/cases/cases-api-get-case.asciidoc @@ -0,0 +1,100 @@ +[[cases-api-get-case]] +== Get case API +++++ +Get case +++++ + +Returns a specified case. + +=== Request + +`GET :/api/cases/` + +`GET :/s//api/cases/` + +=== Prerequisite + +You must have `read` privileges for the *Cases* feature in the *Management*, +*{observability}*, or *Security* section of the +<>, depending on the +`owner` of the cases you're seeking. + +=== Path parameters + +``:: +(Required, string) An identifier for the case to retrieve. Use +<> to retrieve case IDs. + +``:: +(Optional, string) An identifier for the space. If it is not specified, the +default space is used. + +=== Query parameters + +`includeComments`:: +(Optional, boolean) Determines whether case comments are returned. Defaults to +`true`. deprecated:[8.1.0, "The `includeComments` query parameter is deprecated and will be removed in a future release."] + + +==== Response code + +`200`:: + Indicates a successful call. + +==== Example + +Returns case ID `a18b38a0-71b0-11ea-a0b2-c51ea50a58e2` without comments: + +[source,sh] +-------------------------------------------------- +GET api/cases/a18b38a0-71b0-11ea-a0b2-c51ea50a58e2 +-------------------------------------------------- +// KIBANA + +The API returns a JSON object with the retrieved case. For example: + +[source,json] +-------------------------------------------------- +{ + "id": "a18b38a0-71b0-11ea-a0b2-c51ea50a58e2", + "version": "Wzk4LDFd", + "comments": [], + "totalComment": 0, + "closed_at": null, + "closed_by": null, + "created_at": "2020-03-29T11:30:02.658Z", + "created_by": { + "email": "ahunley@imf.usa.gov", + "full_name": "Alan Hunley", + "username": "ahunley" + }, + "external_service": null, + "updated_at": "2020-03-29T12:01:50.244Z", + "updated_by": { + "full_name": "Classified", + "email": "classified@hms.oo.gov.uk", + "username": "M" + }, + "description": "James Bond clicked on a highly suspicious email banner advertising cheap holidays for underpaid civil servants. Operation bubblegum is active. Repeat - operation bubblegum is now active!", + "title": "This case will self-destruct in 5 seconds", + "status": "open", + "connector": { + "id": "131d4448-abe0-4789-939d-8ef60680b498", + "name": "My connector", + "type": ".jira", + "fields": { + "issueType": "10006", + "priority": "High", + } + }, + "settings": { + "syncAlerts": true + }, + "owner": "securitySolution", + "tags": [ + "phishing", + "social engineering", + "bubblegum" + ] +} +-------------------------------------------------- \ No newline at end of file From 5fda6d56988a549297211ecaf70b6e9885ec67c9 Mon Sep 17 00:00:00 2001 From: Esteban Beltran Date: Tue, 29 Mar 2022 17:31:28 +0200 Subject: [PATCH 31/31] [Cases] Show red color when overing the delete button in the cases table (#128718) --- x-pack/plugins/cases/public/components/all_cases/actions.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/x-pack/plugins/cases/public/components/all_cases/actions.tsx b/x-pack/plugins/cases/public/components/all_cases/actions.tsx index d9e0e0ef025c8..f978cd1b3f205 100644 --- a/x-pack/plugins/cases/public/components/all_cases/actions.tsx +++ b/x-pack/plugins/cases/public/components/all_cases/actions.tsx @@ -20,6 +20,7 @@ export const getActions = ({ { description: i18n.DELETE_CASE(), icon: 'trash', + color: 'danger', name: i18n.DELETE_CASE(), onClick: deleteCaseOnClick, type: 'icon',