mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[RAM][O11Y] Integrate Conditional Actions with several Observability rule types (#159522)
## Summary
Closes #159520
<img width="573" alt="Screenshot 2023-06-12 at 3 12 27 PM"
src="ec16b8d7
-25a5-435c-bf29-7392747b8c0f">
### Checklist
- [ ] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
---------
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Patryk Kopyciński <contact@patrykkopycinski.com>
This commit is contained in:
parent
3bd43abd69
commit
faadf347ae
25 changed files with 111 additions and 11 deletions
|
@ -72,6 +72,7 @@ type AuthorizedConsumers = Record<string, HasPrivileges>;
|
||||||
export interface RegistryAlertTypeWithAuth extends RegistryRuleType {
|
export interface RegistryAlertTypeWithAuth extends RegistryRuleType {
|
||||||
authorizedConsumers: AuthorizedConsumers;
|
authorizedConsumers: AuthorizedConsumers;
|
||||||
hasGetSummarizedAlerts?: boolean;
|
hasGetSummarizedAlerts?: boolean;
|
||||||
|
hasFieldsForAAD?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
type IsAuthorizedAtProducerLevel = boolean;
|
type IsAuthorizedAtProducerLevel = boolean;
|
||||||
|
|
|
@ -88,6 +88,7 @@ describe('ruleTypesRoute', () => {
|
||||||
producer: 'test',
|
producer: 'test',
|
||||||
enabled_in_license: true,
|
enabled_in_license: true,
|
||||||
has_get_summarized_alerts: true,
|
has_get_summarized_alerts: true,
|
||||||
|
has_fields_for_a_a_d: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes));
|
rulesClient.listRuleTypes.mockResolvedValueOnce(new Set(listTypes));
|
||||||
|
@ -113,6 +114,7 @@ describe('ruleTypesRoute', () => {
|
||||||
"default_schedule_interval": "10m",
|
"default_schedule_interval": "10m",
|
||||||
"does_set_recovery_context": false,
|
"does_set_recovery_context": false,
|
||||||
"enabled_in_license": true,
|
"enabled_in_license": true,
|
||||||
|
"has_fields_for_a_a_d": false,
|
||||||
"has_get_summarized_alerts": true,
|
"has_get_summarized_alerts": true,
|
||||||
"id": "1",
|
"id": "1",
|
||||||
"is_exportable": true,
|
"is_exportable": true,
|
||||||
|
|
|
@ -26,6 +26,7 @@ const rewriteBodyRes: RewriteResponseCase<RegistryAlertTypeWithAuth[]> = (result
|
||||||
defaultScheduleInterval,
|
defaultScheduleInterval,
|
||||||
doesSetRecoveryContext,
|
doesSetRecoveryContext,
|
||||||
hasGetSummarizedAlerts,
|
hasGetSummarizedAlerts,
|
||||||
|
hasFieldsForAAD,
|
||||||
...rest
|
...rest
|
||||||
}) => ({
|
}) => ({
|
||||||
...rest,
|
...rest,
|
||||||
|
@ -41,6 +42,7 @@ const rewriteBodyRes: RewriteResponseCase<RegistryAlertTypeWithAuth[]> = (result
|
||||||
default_schedule_interval: defaultScheduleInterval,
|
default_schedule_interval: defaultScheduleInterval,
|
||||||
does_set_recovery_context: doesSetRecoveryContext,
|
does_set_recovery_context: doesSetRecoveryContext,
|
||||||
has_get_summarized_alerts: !!hasGetSummarizedAlerts,
|
has_get_summarized_alerts: !!hasGetSummarizedAlerts,
|
||||||
|
has_fields_for_a_a_d: !!hasFieldsForAAD,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -704,6 +704,7 @@ describe('Create Lifecycle', () => {
|
||||||
"defaultScheduleInterval": undefined,
|
"defaultScheduleInterval": undefined,
|
||||||
"doesSetRecoveryContext": false,
|
"doesSetRecoveryContext": false,
|
||||||
"enabledInLicense": false,
|
"enabledInLicense": false,
|
||||||
|
"hasFieldsForAAD": false,
|
||||||
"hasGetSummarizedAlerts": false,
|
"hasGetSummarizedAlerts": false,
|
||||||
"id": "test",
|
"id": "test",
|
||||||
"isExportable": true,
|
"isExportable": true,
|
||||||
|
|
|
@ -61,6 +61,7 @@ export interface RegistryRuleType
|
||||||
| 'ruleTaskTimeout'
|
| 'ruleTaskTimeout'
|
||||||
| 'defaultScheduleInterval'
|
| 'defaultScheduleInterval'
|
||||||
| 'doesSetRecoveryContext'
|
| 'doesSetRecoveryContext'
|
||||||
|
| 'fieldsForAAD'
|
||||||
> {
|
> {
|
||||||
id: string;
|
id: string;
|
||||||
enabledInLicense: boolean;
|
enabledInLicense: boolean;
|
||||||
|
@ -372,6 +373,7 @@ export class RuleTypeRegistry {
|
||||||
doesSetRecoveryContext,
|
doesSetRecoveryContext,
|
||||||
alerts,
|
alerts,
|
||||||
getSummarizedAlerts,
|
getSummarizedAlerts,
|
||||||
|
fieldsForAAD,
|
||||||
},
|
},
|
||||||
]: [string, UntypedNormalizedRuleType]) => ({
|
]: [string, UntypedNormalizedRuleType]) => ({
|
||||||
id,
|
id,
|
||||||
|
@ -392,6 +394,7 @@ export class RuleTypeRegistry {
|
||||||
minimumLicenseRequired
|
minimumLicenseRequired
|
||||||
).isValid,
|
).isValid,
|
||||||
hasGetSummarizedAlerts: !!getSummarizedAlerts,
|
hasGetSummarizedAlerts: !!getSummarizedAlerts,
|
||||||
|
hasFieldsForAAD: Boolean(fieldsForAAD),
|
||||||
...(alerts ? { alerts } : {}),
|
...(alerts ? { alerts } : {}),
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
|
@ -49,6 +49,7 @@ import {
|
||||||
WARNING_ACTIONS,
|
WARNING_ACTIONS,
|
||||||
} from './inventory_metric_threshold_executor';
|
} from './inventory_metric_threshold_executor';
|
||||||
import { MetricsRulesTypeAlertDefinition } from '../register_rule_types';
|
import { MetricsRulesTypeAlertDefinition } from '../register_rule_types';
|
||||||
|
import { O11Y_AAD_FIELDS } from '../../../../common/constants';
|
||||||
|
|
||||||
const condition = schema.object({
|
const condition = schema.object({
|
||||||
threshold: schema.arrayOf(schema.number()),
|
threshold: schema.arrayOf(schema.number()),
|
||||||
|
@ -146,5 +147,6 @@ export async function registerMetricInventoryThresholdRuleType(
|
||||||
},
|
},
|
||||||
getSummarizedAlerts: libs.metricsRules.createGetSummarizedAlerts(),
|
getSummarizedAlerts: libs.metricsRules.createGetSummarizedAlerts(),
|
||||||
alerts: MetricsRulesTypeAlertDefinition,
|
alerts: MetricsRulesTypeAlertDefinition,
|
||||||
|
fieldsForAAD: O11Y_AAD_FIELDS,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { PluginSetupContract } from '@kbn/alerting-plugin/server';
|
import { PluginSetupContract } from '@kbn/alerting-plugin/server';
|
||||||
|
import { O11Y_AAD_FIELDS } from '../../../../common/constants';
|
||||||
import { createLogThresholdExecutor, FIRED_ACTIONS } from './log_threshold_executor';
|
import { createLogThresholdExecutor, FIRED_ACTIONS } from './log_threshold_executor';
|
||||||
import { extractReferences, injectReferences } from './log_threshold_references_manager';
|
import { extractReferences, injectReferences } from './log_threshold_references_manager';
|
||||||
import {
|
import {
|
||||||
|
@ -165,5 +166,6 @@ export async function registerLogThresholdRuleType(
|
||||||
injectReferences,
|
injectReferences,
|
||||||
},
|
},
|
||||||
alerts: LogsRulesTypeAlertDefinition,
|
alerts: LogsRulesTypeAlertDefinition,
|
||||||
|
fieldsForAAD: O11Y_AAD_FIELDS,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
AlertInstanceContext as AlertContext,
|
AlertInstanceContext as AlertContext,
|
||||||
} from '@kbn/alerting-plugin/server';
|
} from '@kbn/alerting-plugin/server';
|
||||||
import { RecoveredActionGroupId } from '@kbn/alerting-plugin/common';
|
import { RecoveredActionGroupId } from '@kbn/alerting-plugin/common';
|
||||||
|
import { O11Y_AAD_FIELDS } from '../../../../common/constants';
|
||||||
import {
|
import {
|
||||||
createMetricAnomalyExecutor,
|
createMetricAnomalyExecutor,
|
||||||
FIRED_ACTIONS,
|
FIRED_ACTIONS,
|
||||||
|
@ -67,6 +68,7 @@ export const registerMetricAnomalyRuleType = (
|
||||||
minimumLicenseRequired: 'basic',
|
minimumLicenseRequired: 'basic',
|
||||||
isExportable: true,
|
isExportable: true,
|
||||||
executor: createMetricAnomalyExecutor(libs, ml),
|
executor: createMetricAnomalyExecutor(libs, ml),
|
||||||
|
fieldsForAAD: O11Y_AAD_FIELDS,
|
||||||
actionVariables: {
|
actionVariables: {
|
||||||
context: [
|
context: [
|
||||||
{ name: 'alertState', description: alertStateActionVariableDescription },
|
{ name: 'alertState', description: alertStateActionVariableDescription },
|
||||||
|
|
|
@ -252,6 +252,7 @@ describe('alert_form', () => {
|
||||||
}
|
}
|
||||||
actionTypeRegistry={actionTypeRegistry}
|
actionTypeRegistry={actionTypeRegistry}
|
||||||
featureId="alerting"
|
featureId="alerting"
|
||||||
|
producerId="alerting"
|
||||||
/>
|
/>
|
||||||
</KibanaReactContext.Provider>
|
</KibanaReactContext.Provider>
|
||||||
</I18nProvider>
|
</I18nProvider>
|
||||||
|
|
|
@ -23,6 +23,7 @@ import type {
|
||||||
} from '@kbn/alerting-plugin/common';
|
} from '@kbn/alerting-plugin/common';
|
||||||
import { SecurityConnectorFeatureId } from '@kbn/actions-plugin/common';
|
import { SecurityConnectorFeatureId } from '@kbn/actions-plugin/common';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { AlertConsumers } from '@kbn/rule-data-utils';
|
||||||
import { NOTIFICATION_DEFAULT_FREQUENCY } from '../../../../../common/constants';
|
import { NOTIFICATION_DEFAULT_FREQUENCY } from '../../../../../common/constants';
|
||||||
import type { FieldHook } from '../../../../shared_imports';
|
import type { FieldHook } from '../../../../shared_imports';
|
||||||
import { useFormContext } from '../../../../shared_imports';
|
import { useFormContext } from '../../../../shared_imports';
|
||||||
|
@ -243,13 +244,13 @@ export const RuleActionsField: React.FC<Props> = ({
|
||||||
setActionFrequencyProperty: setActionFrequency,
|
setActionFrequencyProperty: setActionFrequency,
|
||||||
setActionAlertsFilterProperty,
|
setActionAlertsFilterProperty,
|
||||||
featureId: SecurityConnectorFeatureId,
|
featureId: SecurityConnectorFeatureId,
|
||||||
|
producerId: AlertConsumers.SIEM,
|
||||||
defaultActionMessage: FORM_FOR_EACH_ALERT_BODY_MESSAGE,
|
defaultActionMessage: FORM_FOR_EACH_ALERT_BODY_MESSAGE,
|
||||||
defaultSummaryMessage: FORM_SUMMARY_BODY_MESSAGE,
|
defaultSummaryMessage: FORM_SUMMARY_BODY_MESSAGE,
|
||||||
hideActionHeader: true,
|
hideActionHeader: true,
|
||||||
hasSummary: true,
|
hasSummary: true,
|
||||||
notifyWhenSelectOptions: NOTIFY_WHEN_OPTIONS,
|
notifyWhenSelectOptions: NOTIFY_WHEN_OPTIONS,
|
||||||
defaultRuleFrequency: NOTIFICATION_DEFAULT_FREQUENCY,
|
defaultRuleFrequency: NOTIFICATION_DEFAULT_FREQUENCY,
|
||||||
showActionAlertsFilter: true,
|
|
||||||
}),
|
}),
|
||||||
[
|
[
|
||||||
actions,
|
actions,
|
||||||
|
|
|
@ -100,6 +100,7 @@ const baseProps = {
|
||||||
recoveryActionGroup: 'recovered',
|
recoveryActionGroup: 'recovered',
|
||||||
actionTypeRegistry,
|
actionTypeRegistry,
|
||||||
minimumThrottleInterval: [1, 'm'] as [number | undefined, string],
|
minimumThrottleInterval: [1, 'm'] as [number | undefined, string],
|
||||||
|
producerId: 'infratstructure',
|
||||||
setActions: jest.fn(),
|
setActions: jest.fn(),
|
||||||
setActionIdByIndex: jest.fn(),
|
setActionIdByIndex: jest.fn(),
|
||||||
setActionParamsProperty: jest.fn(),
|
setActionParamsProperty: jest.fn(),
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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 { DataViewField } from '@kbn/data-views-plugin/common';
|
||||||
|
import { useKibana } from '@kbn/kibana-react-plugin/public';
|
||||||
|
import { BASE_RAC_ALERTS_API_PATH } from '@kbn/rule-registry-plugin/common';
|
||||||
|
import useAsync from 'react-use/lib/useAsync';
|
||||||
|
import type { AsyncState } from 'react-use/lib/useAsync';
|
||||||
|
import { TriggersAndActionsUiServices } from '../..';
|
||||||
|
|
||||||
|
export function useRuleAADFields(ruleTypeId?: string): AsyncState<DataViewField[]> {
|
||||||
|
const { http } = useKibana<TriggersAndActionsUiServices>().services;
|
||||||
|
|
||||||
|
const aadFields = useAsync(async () => {
|
||||||
|
if (!ruleTypeId) return [];
|
||||||
|
const fields = await http.get<DataViewField[]>(`${BASE_RAC_ALERTS_API_PATH}/aad_fields`, {
|
||||||
|
query: { ruleTypeId },
|
||||||
|
});
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
});
|
||||||
|
|
||||||
|
return aadFields;
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ const rewriteBodyReq: RewriteRequestCase<RuleType> = ({
|
||||||
does_set_recovery_context: doesSetRecoveryContext,
|
does_set_recovery_context: doesSetRecoveryContext,
|
||||||
default_schedule_interval: defaultScheduleInterval,
|
default_schedule_interval: defaultScheduleInterval,
|
||||||
has_get_summarized_alerts: hasGetSummarizedAlerts,
|
has_get_summarized_alerts: hasGetSummarizedAlerts,
|
||||||
|
has_fields_for_a_a_d: hasFieldsForAAD,
|
||||||
...rest
|
...rest
|
||||||
}: AsApiContract<RuleType>) => ({
|
}: AsApiContract<RuleType>) => ({
|
||||||
enabledInLicense,
|
enabledInLicense,
|
||||||
|
@ -38,6 +39,7 @@ const rewriteBodyReq: RewriteRequestCase<RuleType> = ({
|
||||||
doesSetRecoveryContext,
|
doesSetRecoveryContext,
|
||||||
defaultScheduleInterval,
|
defaultScheduleInterval,
|
||||||
hasGetSummarizedAlerts,
|
hasGetSummarizedAlerts,
|
||||||
|
hasFieldsForAAD,
|
||||||
...rest,
|
...rest,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useState, useCallback, useMemo, useEffect } from 'react';
|
import React, { useState, useCallback, useMemo, useEffect } from 'react';
|
||||||
|
import { ValidFeatureId } from '@kbn/rule-data-utils';
|
||||||
import { Filter } from '@kbn/es-query';
|
import { Filter } from '@kbn/es-query';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { EuiSwitch, EuiSpacer } from '@elastic/eui';
|
import { EuiSwitch, EuiSpacer } from '@elastic/eui';
|
||||||
|
@ -16,11 +17,17 @@ import { AlertsSearchBar } from '../alerts_search_bar';
|
||||||
interface ActionAlertsFilterQueryProps {
|
interface ActionAlertsFilterQueryProps {
|
||||||
state?: AlertsFilter['query'];
|
state?: AlertsFilter['query'];
|
||||||
onChange: (update?: AlertsFilter['query']) => void;
|
onChange: (update?: AlertsFilter['query']) => void;
|
||||||
|
appName: string;
|
||||||
|
featureIds: ValidFeatureId[];
|
||||||
|
ruleTypeId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ActionAlertsFilterQuery: React.FC<ActionAlertsFilterQueryProps> = ({
|
export const ActionAlertsFilterQuery: React.FC<ActionAlertsFilterQueryProps> = ({
|
||||||
state,
|
state,
|
||||||
onChange,
|
onChange,
|
||||||
|
appName,
|
||||||
|
featureIds,
|
||||||
|
ruleTypeId,
|
||||||
}) => {
|
}) => {
|
||||||
const [query, setQuery] = useState(state ?? { kql: '', filters: [] });
|
const [query, setQuery] = useState(state ?? { kql: '', filters: [] });
|
||||||
|
|
||||||
|
@ -61,7 +68,7 @@ export const ActionAlertsFilterQuery: React.FC<ActionAlertsFilterQueryProps> = (
|
||||||
label={i18n.translate(
|
label={i18n.translate(
|
||||||
'xpack.triggersActionsUI.sections.actionTypeForm.ActionAlertsFilterQueryToggleLabel',
|
'xpack.triggersActionsUI.sections.actionTypeForm.ActionAlertsFilterQueryToggleLabel',
|
||||||
{
|
{
|
||||||
defaultMessage: 'if alert matches a query',
|
defaultMessage: 'If alert matches a query',
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
checked={queryEnabled}
|
checked={queryEnabled}
|
||||||
|
@ -72,9 +79,10 @@ export const ActionAlertsFilterQuery: React.FC<ActionAlertsFilterQueryProps> = (
|
||||||
<>
|
<>
|
||||||
<EuiSpacer size="s" />
|
<EuiSpacer size="s" />
|
||||||
<AlertsSearchBar
|
<AlertsSearchBar
|
||||||
appName="siem"
|
appName={appName}
|
||||||
|
featureIds={featureIds}
|
||||||
|
ruleTypeId={ruleTypeId}
|
||||||
disableQueryLanguageSwitcher={true}
|
disableQueryLanguageSwitcher={true}
|
||||||
featureIds={['siem']}
|
|
||||||
query={query.kql}
|
query={query.kql}
|
||||||
filters={query.filters ?? []}
|
filters={query.filters ?? []}
|
||||||
onQueryChange={onQueryChange}
|
onQueryChange={onQueryChange}
|
||||||
|
|
|
@ -146,7 +146,7 @@ export const ActionAlertsFilterTimeframe: React.FC<ActionAlertsFilterTimeframePr
|
||||||
label={i18n.translate(
|
label={i18n.translate(
|
||||||
'xpack.triggersActionsUI.sections.actionTypeForm.ActionAlertsFilterTimeframeToggleLabel',
|
'xpack.triggersActionsUI.sections.actionTypeForm.ActionAlertsFilterTimeframeToggleLabel',
|
||||||
{
|
{
|
||||||
defaultMessage: 'if alert is generated during timeframe',
|
defaultMessage: 'If alert is generated during timeframe',
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
checked={timeframeEnabled}
|
checked={timeframeEnabled}
|
||||||
|
|
|
@ -314,6 +314,7 @@ describe('action_form', () => {
|
||||||
context: [{ name: 'contextVar', description: 'context var1' }],
|
context: [{ name: 'contextVar', description: 'context var1' }],
|
||||||
}}
|
}}
|
||||||
featureId="alerting"
|
featureId="alerting"
|
||||||
|
producerId="alerting"
|
||||||
defaultActionGroupId={'default'}
|
defaultActionGroupId={'default'}
|
||||||
isActionGroupDisabledForActionType={(actionGroupId: string, actionTypeId: string) => {
|
isActionGroupDisabledForActionType={(actionGroupId: string, actionTypeId: string) => {
|
||||||
const recoveryActionGroupId = customRecoveredActionGroup
|
const recoveryActionGroupId = customRecoveredActionGroup
|
||||||
|
|
|
@ -69,6 +69,7 @@ export interface ActionAccordionFormProps {
|
||||||
index: number
|
index: number
|
||||||
) => void;
|
) => void;
|
||||||
featureId: string;
|
featureId: string;
|
||||||
|
producerId: string;
|
||||||
messageVariables?: ActionVariables;
|
messageVariables?: ActionVariables;
|
||||||
summaryMessageVariables?: ActionVariables;
|
summaryMessageVariables?: ActionVariables;
|
||||||
setHasActionsDisabled?: (value: boolean) => void;
|
setHasActionsDisabled?: (value: boolean) => void;
|
||||||
|
@ -83,7 +84,8 @@ export interface ActionAccordionFormProps {
|
||||||
minimumThrottleInterval?: [number | undefined, string];
|
minimumThrottleInterval?: [number | undefined, string];
|
||||||
notifyWhenSelectOptions?: NotifyWhenSelectOptions[];
|
notifyWhenSelectOptions?: NotifyWhenSelectOptions[];
|
||||||
defaultRuleFrequency?: RuleActionFrequency;
|
defaultRuleFrequency?: RuleActionFrequency;
|
||||||
showActionAlertsFilter?: boolean;
|
ruleTypeId?: string;
|
||||||
|
hasFieldsForAAD?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ActiveActionConnectorState {
|
interface ActiveActionConnectorState {
|
||||||
|
@ -117,7 +119,9 @@ export const ActionForm = ({
|
||||||
minimumThrottleInterval,
|
minimumThrottleInterval,
|
||||||
notifyWhenSelectOptions,
|
notifyWhenSelectOptions,
|
||||||
defaultRuleFrequency = DEFAULT_FREQUENCY,
|
defaultRuleFrequency = DEFAULT_FREQUENCY,
|
||||||
showActionAlertsFilter,
|
ruleTypeId,
|
||||||
|
producerId,
|
||||||
|
hasFieldsForAAD,
|
||||||
}: ActionAccordionFormProps) => {
|
}: ActionAccordionFormProps) => {
|
||||||
const {
|
const {
|
||||||
http,
|
http,
|
||||||
|
@ -491,7 +495,10 @@ export const ActionForm = ({
|
||||||
minimumThrottleInterval={minimumThrottleInterval}
|
minimumThrottleInterval={minimumThrottleInterval}
|
||||||
notifyWhenSelectOptions={notifyWhenSelectOptions}
|
notifyWhenSelectOptions={notifyWhenSelectOptions}
|
||||||
defaultNotifyWhenValue={defaultRuleFrequency.notifyWhen}
|
defaultNotifyWhenValue={defaultRuleFrequency.notifyWhen}
|
||||||
showActionAlertsFilter={showActionAlertsFilter}
|
featureId={featureId}
|
||||||
|
producerId={producerId}
|
||||||
|
ruleTypeId={ruleTypeId}
|
||||||
|
hasFieldsForAAD={hasFieldsForAAD}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -634,6 +634,8 @@ function getActionTypeForm({
|
||||||
summaryMessageVariables={summaryMessageVariables}
|
summaryMessageVariables={summaryMessageVariables}
|
||||||
notifyWhenSelectOptions={notifyWhenSelectOptions}
|
notifyWhenSelectOptions={notifyWhenSelectOptions}
|
||||||
defaultNotifyWhenValue={defaultNotifyWhenValue}
|
defaultNotifyWhenValue={defaultNotifyWhenValue}
|
||||||
|
producerId="infrastructure"
|
||||||
|
featureId="infrastructure"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import React, { Suspense, useEffect, useState, useCallback, useMemo } from 'react';
|
import React, { Suspense, useEffect, useState, useCallback, useMemo } from 'react';
|
||||||
import { i18n } from '@kbn/i18n';
|
import { i18n } from '@kbn/i18n';
|
||||||
import { FormattedMessage } from '@kbn/i18n-react';
|
import { FormattedMessage } from '@kbn/i18n-react';
|
||||||
|
import { ValidFeatureId, AlertConsumers } from '@kbn/rule-data-utils';
|
||||||
import {
|
import {
|
||||||
EuiFlexGroup,
|
EuiFlexGroup,
|
||||||
EuiFlexItem,
|
EuiFlexItem,
|
||||||
|
@ -87,7 +88,10 @@ export type ActionTypeFormProps = {
|
||||||
minimumThrottleInterval?: [number | undefined, string];
|
minimumThrottleInterval?: [number | undefined, string];
|
||||||
notifyWhenSelectOptions?: NotifyWhenSelectOptions[];
|
notifyWhenSelectOptions?: NotifyWhenSelectOptions[];
|
||||||
defaultNotifyWhenValue?: RuleNotifyWhenType;
|
defaultNotifyWhenValue?: RuleNotifyWhenType;
|
||||||
showActionAlertsFilter?: boolean;
|
featureId: string;
|
||||||
|
producerId: string;
|
||||||
|
ruleTypeId?: string;
|
||||||
|
hasFieldsForAAD?: boolean;
|
||||||
} & Pick<
|
} & Pick<
|
||||||
ActionAccordionFormProps,
|
ActionAccordionFormProps,
|
||||||
| 'defaultActionGroupId'
|
| 'defaultActionGroupId'
|
||||||
|
@ -134,7 +138,10 @@ export const ActionTypeForm = ({
|
||||||
minimumThrottleInterval,
|
minimumThrottleInterval,
|
||||||
notifyWhenSelectOptions,
|
notifyWhenSelectOptions,
|
||||||
defaultNotifyWhenValue,
|
defaultNotifyWhenValue,
|
||||||
showActionAlertsFilter,
|
producerId,
|
||||||
|
featureId,
|
||||||
|
ruleTypeId,
|
||||||
|
hasFieldsForAAD,
|
||||||
}: ActionTypeFormProps) => {
|
}: ActionTypeFormProps) => {
|
||||||
const {
|
const {
|
||||||
application: { capabilities },
|
application: { capabilities },
|
||||||
|
@ -333,6 +340,8 @@ export const ActionTypeForm = ({
|
||||||
setActionGroupIdByIndex &&
|
setActionGroupIdByIndex &&
|
||||||
!actionItem.frequency?.summary;
|
!actionItem.frequency?.summary;
|
||||||
|
|
||||||
|
const showActionAlertsFilter = hasFieldsForAAD || producerId === AlertConsumers.SIEM;
|
||||||
|
|
||||||
const accordionContent = checkEnabledResult.isEnabled ? (
|
const accordionContent = checkEnabledResult.isEnabled ? (
|
||||||
<>
|
<>
|
||||||
<EuiSplitPanel.Inner
|
<EuiSplitPanel.Inner
|
||||||
|
@ -418,6 +427,9 @@ export const ActionTypeForm = ({
|
||||||
<ActionAlertsFilterQuery
|
<ActionAlertsFilterQuery
|
||||||
state={actionItem.alertsFilter?.query}
|
state={actionItem.alertsFilter?.query}
|
||||||
onChange={(query) => setActionAlertsFilterProperty('query', query, index)}
|
onChange={(query) => setActionAlertsFilterProperty('query', query, index)}
|
||||||
|
featureIds={[producerId as ValidFeatureId]}
|
||||||
|
appName={featureId!}
|
||||||
|
ruleTypeId={ruleTypeId}
|
||||||
/>
|
/>
|
||||||
<EuiSpacer size="s" />
|
<EuiSpacer size="s" />
|
||||||
<ActionAlertsFilterTimeframe
|
<ActionAlertsFilterTimeframe
|
||||||
|
|
|
@ -13,12 +13,14 @@ import { SEARCH_BAR_PLACEHOLDER } from './translations';
|
||||||
import { AlertsSearchBarProps, QueryLanguageType } from './types';
|
import { AlertsSearchBarProps, QueryLanguageType } from './types';
|
||||||
import { useAlertDataView } from '../../hooks/use_alert_data_view';
|
import { useAlertDataView } from '../../hooks/use_alert_data_view';
|
||||||
import { TriggersAndActionsUiServices } from '../../..';
|
import { TriggersAndActionsUiServices } from '../../..';
|
||||||
|
import { useRuleAADFields } from '../../hooks/use_rule_aad_fields';
|
||||||
|
|
||||||
// TODO Share buildEsQuery to be used between AlertsSearchBar and AlertsStateTable component https://github.com/elastic/kibana/issues/144615
|
// TODO Share buildEsQuery to be used between AlertsSearchBar and AlertsStateTable component https://github.com/elastic/kibana/issues/144615
|
||||||
export function AlertsSearchBar({
|
export function AlertsSearchBar({
|
||||||
appName,
|
appName,
|
||||||
disableQueryLanguageSwitcher = false,
|
disableQueryLanguageSwitcher = false,
|
||||||
featureIds,
|
featureIds,
|
||||||
|
ruleTypeId,
|
||||||
query,
|
query,
|
||||||
filters,
|
filters,
|
||||||
onQueryChange,
|
onQueryChange,
|
||||||
|
@ -40,6 +42,14 @@ export function AlertsSearchBar({
|
||||||
|
|
||||||
const [queryLanguage, setQueryLanguage] = useState<QueryLanguageType>('kuery');
|
const [queryLanguage, setQueryLanguage] = useState<QueryLanguageType>('kuery');
|
||||||
const { value: dataView, loading, error } = useAlertDataView(featureIds);
|
const { value: dataView, loading, error } = useAlertDataView(featureIds);
|
||||||
|
const {
|
||||||
|
value: aadFields,
|
||||||
|
loading: fieldsLoading,
|
||||||
|
error: fieldsError,
|
||||||
|
} = useRuleAADFields(ruleTypeId);
|
||||||
|
|
||||||
|
const indexPatterns =
|
||||||
|
ruleTypeId && aadFields?.length ? [{ title: ruleTypeId, fields: aadFields }] : [dataView!];
|
||||||
|
|
||||||
const onSearchQuerySubmit = useCallback(
|
const onSearchQuerySubmit = useCallback(
|
||||||
({ dateRange, query: nextQuery }: { dateRange: TimeRange; query?: Query }) => {
|
({ dateRange, query: nextQuery }: { dateRange: TimeRange; query?: Query }) => {
|
||||||
|
@ -72,7 +82,10 @@ export function AlertsSearchBar({
|
||||||
<SearchBar
|
<SearchBar
|
||||||
appName={appName}
|
appName={appName}
|
||||||
disableQueryLanguageSwitcher={disableQueryLanguageSwitcher}
|
disableQueryLanguageSwitcher={disableQueryLanguageSwitcher}
|
||||||
indexPatterns={loading || error ? NO_INDEX_PATTERNS : [dataView!]}
|
// @ts-expect-error - DataView fields prop and SearchBar indexPatterns props are overly broad
|
||||||
|
indexPatterns={
|
||||||
|
loading || error || fieldsLoading || fieldsError ? NO_INDEX_PATTERNS : indexPatterns
|
||||||
|
}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
query={{ query: query ?? '', language: queryLanguage }}
|
query={{ query: query ?? '', language: queryLanguage }}
|
||||||
filters={filters}
|
filters={filters}
|
||||||
|
|
|
@ -23,6 +23,7 @@ export interface AlertsSearchBarProps {
|
||||||
showSubmitButton?: boolean;
|
showSubmitButton?: boolean;
|
||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
submitOnBlur?: boolean;
|
submitOnBlur?: boolean;
|
||||||
|
ruleTypeId?: string;
|
||||||
onQueryChange?: (query: {
|
onQueryChange?: (query: {
|
||||||
dateRange: { from: string; to: string; mode?: 'absolute' | 'relative' };
|
dateRange: { from: string; to: string; mode?: 'absolute' | 'relative' };
|
||||||
query?: string;
|
query?: string;
|
||||||
|
|
|
@ -661,6 +661,9 @@ export const RuleForm = ({
|
||||||
defaultActionGroupId={defaultActionGroupId}
|
defaultActionGroupId={defaultActionGroupId}
|
||||||
hasSummary={selectedRuleType.hasGetSummarizedAlerts}
|
hasSummary={selectedRuleType.hasGetSummarizedAlerts}
|
||||||
featureId={connectorFeatureId}
|
featureId={connectorFeatureId}
|
||||||
|
producerId={selectedRuleType.producer}
|
||||||
|
hasFieldsForAAD={selectedRuleType.hasFieldsForAAD}
|
||||||
|
ruleTypeId={rule.ruleTypeId}
|
||||||
isActionGroupDisabledForActionType={(actionGroupId: string, actionTypeId: string) =>
|
isActionGroupDisabledForActionType={(actionGroupId: string, actionTypeId: string) =>
|
||||||
isActionGroupDisabledForActionType(selectedRuleType, actionGroupId, actionTypeId)
|
isActionGroupDisabledForActionType(selectedRuleType, actionGroupId, actionTypeId)
|
||||||
}
|
}
|
||||||
|
|
|
@ -337,6 +337,7 @@ export interface RuleType<
|
||||||
actionVariables: ActionVariables;
|
actionVariables: ActionVariables;
|
||||||
authorizedConsumers: Record<string, { read: boolean; all: boolean }>;
|
authorizedConsumers: Record<string, { read: boolean; all: boolean }>;
|
||||||
enabledInLicense: boolean;
|
enabledInLicense: boolean;
|
||||||
|
hasFieldsForAAD?: boolean;
|
||||||
hasGetSummarizedAlerts?: boolean;
|
hasGetSummarizedAlerts?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@ export default function listRuleTypes({ getService }: FtrProviderContext) {
|
||||||
name: 'Recovered',
|
name: 'Recovered',
|
||||||
},
|
},
|
||||||
enabled_in_license: true,
|
enabled_in_license: true,
|
||||||
|
has_fields_for_a_a_d: false,
|
||||||
has_get_summarized_alerts: false,
|
has_get_summarized_alerts: false,
|
||||||
rule_task_timeout: '5m',
|
rule_task_timeout: '5m',
|
||||||
};
|
};
|
||||||
|
@ -63,6 +64,7 @@ export default function listRuleTypes({ getService }: FtrProviderContext) {
|
||||||
minimum_license_required: 'basic',
|
minimum_license_required: 'basic',
|
||||||
is_exportable: true,
|
is_exportable: true,
|
||||||
enabled_in_license: true,
|
enabled_in_license: true,
|
||||||
|
has_fields_for_a_a_d: false,
|
||||||
has_get_summarized_alerts: false,
|
has_get_summarized_alerts: false,
|
||||||
rule_task_timeout: '5m',
|
rule_task_timeout: '5m',
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,6 +45,7 @@ export default function listRuleTypes({ getService }: FtrProviderContext) {
|
||||||
minimum_license_required: 'basic',
|
minimum_license_required: 'basic',
|
||||||
is_exportable: true,
|
is_exportable: true,
|
||||||
enabled_in_license: true,
|
enabled_in_license: true,
|
||||||
|
has_fields_for_a_a_d: false,
|
||||||
has_get_summarized_alerts: false,
|
has_get_summarized_alerts: false,
|
||||||
rule_task_timeout: '5m',
|
rule_task_timeout: '5m',
|
||||||
});
|
});
|
||||||
|
@ -133,6 +134,7 @@ export default function listRuleTypes({ getService }: FtrProviderContext) {
|
||||||
minimumLicenseRequired: 'basic',
|
minimumLicenseRequired: 'basic',
|
||||||
isExportable: true,
|
isExportable: true,
|
||||||
enabledInLicense: true,
|
enabledInLicense: true,
|
||||||
|
hasFieldsForAAD: false,
|
||||||
hasGetSummarizedAlerts: false,
|
hasGetSummarizedAlerts: false,
|
||||||
ruleTaskTimeout: '5m',
|
ruleTaskTimeout: '5m',
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue