Skip to content

Commit 5ff13ad

Browse files
authored
Add custom action to registry and show actions list in siem (#58395)
* Add custom action to registry and show actions list in siem * Exposed action form as reusable component * Fixed few small bugs * Fixed red ci * Fixed type checks * Fixed failed tests * Fixed due to comments * Fixed type check errors * Fixed plugin check * Rebalancing CI groups according to #58930 * Fixed merge issues
1 parent c4b385d commit 5ff13ad

File tree

15 files changed

+830
-511
lines changed

15 files changed

+830
-511
lines changed

x-pack/plugins/triggers_actions_ui/README.md

Lines changed: 155 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ Table of Contents
4343
- [Action type model definition](#action-type-model-definition)
4444
- [Register action type model](#register-action-type-model)
4545
- [Create and register new action type UI example](#reate-and-register-new-action-type-ui-example)
46+
- [Embed the Alert Actions form within any Kibana plugin](#embed-the-alert-actions-form-within-any-kibana-plugin)
4647
- [Embed the Create Connector flyout within any Kibana plugin](#embed-the-create-connector-flyout-within-any-kibana-plugin)
4748
- [Embed the Edit Connector flyout within any Kibana plugin](#embed-the-edit-connector-flyout-within-any-kibana-plugin)
4849

@@ -71,7 +72,7 @@ AlertTypeModel:
7172
```
7273
export function getAlertType(): AlertTypeModel {
7374
return {
74-
id: 'threshold',
75+
id: '.index-threshold',
7576
name: 'Index Threshold',
7677
iconClass: 'alert',
7778
alertParamsExpression: IndexThresholdAlertTypeExpression,
@@ -660,8 +661,6 @@ const [alertFlyoutVisible, setAlertFlyoutVisibility] = useState<boolean>(false);
660661
// in render section of component
661662
<AlertsContextProvider
662663
value={{
663-
addFlyoutVisible: alertFlyoutVisible,
664-
setAddFlyoutVisibility: setAlertFlyoutVisibility,
665664
http,
666665
actionTypeRegistry: triggers_actions_ui.actionTypeRegistry,
667666
alertTypeRegistry: triggers_actions_ui.alertTypeRegistry,
@@ -672,14 +671,17 @@ const [alertFlyoutVisible, setAlertFlyoutVisibility] = useState<boolean>(false);
672671
metadata: { test: 'some value', fields: ['test'] },
673672
}}
674673
>
675-
<AlertAdd consumer={'watcher'} />
674+
<AlertAdd consumer={'watcher'} addFlyoutVisible={alertFlyoutVisible}
675+
setAddFlyoutVisibility={setAlertFlyoutVisibility} />
676676
</AlertsContextProvider>
677677
```
678678

679679
AlertAdd Props definition:
680680
```
681681
interface AlertAddProps {
682682
consumer: string;
683+
addFlyoutVisible: boolean;
684+
setAddFlyoutVisibility: React.Dispatch<React.SetStateAction<boolean>>;
683685
alertTypeId?: string;
684686
canChangeTrigger?: boolean;
685687
}
@@ -688,20 +690,20 @@ interface AlertAddProps {
688690
|Property|Description|
689691
|---|---|
690692
|consumer|Name of the plugin that creates an alert.|
693+
|addFlyoutVisible|Visibility state of the Create Alert flyout.|
694+
|setAddFlyoutVisibility|Function for changing visibility state of the Create Alert flyout.|
691695
|alertTypeId|Optional property to preselect alert type.|
692696
|canChangeTrigger|Optional property, that hides change alert type possibility.|
693697

694698
AlertsContextProvider value options:
695699
```
696700
export interface AlertsContextValue<MetaData = Record<string, any>> {
697-
addFlyoutVisible: boolean;
698-
setAddFlyoutVisibility: React.Dispatch<React.SetStateAction<boolean>>;
699701
reloadAlerts?: () => Promise<void>;
700702
http: HttpSetup;
701703
alertTypeRegistry: TypeRegistry<AlertTypeModel>;
702704
actionTypeRegistry: TypeRegistry<ActionTypeModel>;
703705
uiSettings?: IUiSettingsClient;
704-
toastNotifications?: Pick<
706+
toastNotifications: Pick<
705707
ToastsApi,
706708
'get$' | 'add' | 'remove' | 'addSuccess' | 'addWarning' | 'addDanger' | 'addError'
707709
>;
@@ -713,14 +715,12 @@ export interface AlertsContextValue<MetaData = Record<string, any>> {
713715

714716
|Property|Description|
715717
|---|---|
716-
|addFlyoutVisible|Visibility state of the Create Alert flyout.|
717-
|setAddFlyoutVisibility|Function for changing visibility state of the Create Alert flyout.|
718718
|reloadAlerts|Optional function, which will be executed if alert was saved sucsessfuly.|
719719
|http|HttpSetup needed for executing API calls.|
720720
|alertTypeRegistry|Registry for alert types.|
721721
|actionTypeRegistry|Registry for action types.|
722722
|uiSettings|Optional property, which is needed to display visualization of alert type expression. Will be changed after visualization refactoring.|
723-
|toastNotifications|Optional toast messages.|
723+
|toastNotifications|Toast messages.|
724724
|charts|Optional property, which is needed to display visualization of alert type expression. Will be changed after visualization refactoring.|
725725
|dataFieldsFormats|Optional property, which is needed to display visualization of alert type expression. Will be changed after visualization refactoring.|
726726
|metadata|Optional generic property, which allows to define component specific metadata. This metadata can be used for passing down preloaded data for Alert type expression component.|
@@ -1204,6 +1204,150 @@ Clicking on the select card for `Example Action Type` will open the action type
12041204
or create a new connector:
12051205
![Example Action Type with empty connectors list](https://i.imgur.com/EamA9Xv.png)
12061206

1207+
## Embed the Alert Actions form within any Kibana plugin
1208+
1209+
Follow the instructions bellow to embed the Alert Actions form within any Kibana plugin:
1210+
1. Add TriggersAndActionsUIPublicPluginSetup and TriggersAndActionsUIPublicPluginStart to Kibana plugin setup dependencies:
1211+
1212+
```
1213+
import {
1214+
TriggersAndActionsUIPublicPluginSetup,
1215+
TriggersAndActionsUIPublicPluginStart,
1216+
} from '../../../../../x-pack/plugins/triggers_actions_ui/public';
1217+
1218+
triggers_actions_ui: TriggersAndActionsUIPublicPluginSetup;
1219+
...
1220+
1221+
triggers_actions_ui: TriggersAndActionsUIPublicPluginStart;
1222+
```
1223+
Then this dependencies will be used to embed Actions form or register your own action type.
1224+
1225+
2. Add Actions form to React component:
1226+
1227+
```
1228+
import React, { useCallback } from 'react';
1229+
import { ActionForm } from '../../../../../../../../../plugins/triggers_actions_ui/public';
1230+
import { AlertAction } from '../../../../../../../../../plugins/triggers_actions_ui/public/types';
1231+
1232+
const ALOWED_BY_PLUGIN_ACTION_TYPES = [
1233+
{ id: '.email', name: 'Email', enabled: true },
1234+
{ id: '.index', name: 'Index', enabled: false },
1235+
{ id: '.example-action', name: 'Example Action', enabled: false },
1236+
];
1237+
1238+
export const ComponentWithActionsForm: () => {
1239+
const { http, triggers_actions_ui, toastNotifications } = useKibana().services;
1240+
const actionTypeRegistry = triggers_actions_ui.actionTypeRegistry;
1241+
const initialAlert = ({
1242+
name: 'test',
1243+
params: {},
1244+
consumer: 'alerting',
1245+
alertTypeId: '.index-threshold',
1246+
schedule: {
1247+
interval: '1m',
1248+
},
1249+
actions: [
1250+
{
1251+
group: 'default',
1252+
id: 'test',
1253+
actionTypeId: '.index',
1254+
params: {
1255+
message: '',
1256+
},
1257+
},
1258+
],
1259+
tags: [],
1260+
muteAll: false,
1261+
enabled: false,
1262+
mutedInstanceIds: [],
1263+
} as unknown) as Alert;
1264+
1265+
return (
1266+
<ActionForm
1267+
actions={initialAlert.actions}
1268+
messageVariables={['test var1', 'test var2']}
1269+
defaultActionGroupId={'default'}
1270+
setActionIdByIndex={(id: string, index: number) => {
1271+
initialAlert.actions[index].id = id;
1272+
}}
1273+
setAlertProperty={(_updatedActions: AlertAction[]) => {}}
1274+
setActionParamsProperty={(key: string, value: any, index: number) =>
1275+
(initialAlert.actions[index] = { ...initialAlert.actions[index], [key]: value })
1276+
}
1277+
http={http}
1278+
actionTypeRegistry={actionTypeRegistry}
1279+
defaultActionMessage={'Alert [{{ctx.metadata.name}}] has exceeded the threshold'}
1280+
actionTypes={ALOWED_BY_PLUGIN_ACTION_TYPES}
1281+
toastNotifications={toastNotifications}
1282+
/>
1283+
);
1284+
};
1285+
```
1286+
1287+
ActionForm Props definition:
1288+
```
1289+
interface ActionAccordionFormProps {
1290+
actions: AlertAction[];
1291+
defaultActionGroupId: string;
1292+
setActionIdByIndex: (id: string, index: number) => void;
1293+
setAlertProperty: (actions: AlertAction[]) => void;
1294+
setActionParamsProperty: (key: string, value: any, index: number) => void;
1295+
http: HttpSetup;
1296+
actionTypeRegistry: TypeRegistry<ActionTypeModel>;
1297+
toastNotifications: Pick<
1298+
ToastsApi,
1299+
'get$' | 'add' | 'remove' | 'addSuccess' | 'addWarning' | 'addDanger' | 'addError'
1300+
>;
1301+
actionTypes?: ActionType[];
1302+
messageVariables?: string[];
1303+
defaultActionMessage?: string;
1304+
}
1305+
1306+
```
1307+
1308+
|Property|Description|
1309+
|---|---|
1310+
|actions|List of actions comes from alert.actions property.|
1311+
|defaultActionGroupId|Default action group id to which each new action will belong to.|
1312+
|setActionIdByIndex|Function for changing action 'id' by the proper index in alert.actions array.|
1313+
|setAlertProperty|Function for changing alert property 'actions'. Used when deleting action from the array to reset it.|
1314+
|setActionParamsProperty|Function for changing action key/value property by index in alert.actions array.|
1315+
|http|HttpSetup needed for executing API calls.|
1316+
|actionTypeRegistry|Registry for action types.|
1317+
|toastNotifications|Toast messages.|
1318+
|actionTypes|Optional property, which allowes to define a list of available actions specific for a current plugin.|
1319+
|actionTypes|Optional property, which allowes to define a list of variables for action 'message' property.|
1320+
|defaultActionMessage|Optional property, which allowes to define a message value for action with 'message' property.|
1321+
1322+
1323+
AlertsContextProvider value options:
1324+
```
1325+
export interface AlertsContextValue {
1326+
reloadAlerts?: () => Promise<void>;
1327+
http: HttpSetup;
1328+
alertTypeRegistry: TypeRegistry<AlertTypeModel>;
1329+
actionTypeRegistry: TypeRegistry<ActionTypeModel>;
1330+
uiSettings?: IUiSettingsClient;
1331+
toastNotifications: Pick<
1332+
ToastsApi,
1333+
'get$' | 'add' | 'remove' | 'addSuccess' | 'addWarning' | 'addDanger' | 'addError'
1334+
>;
1335+
charts?: ChartsPluginSetup;
1336+
dataFieldsFormats?: Pick<FieldFormatsRegistry, 'register'>;
1337+
}
1338+
```
1339+
1340+
|Property|Description|
1341+
|---|---|
1342+
|reloadAlerts|Optional function, which will be executed if alert was saved sucsessfuly.|
1343+
|http|HttpSetup needed for executing API calls.|
1344+
|alertTypeRegistry|Registry for alert types.|
1345+
|actionTypeRegistry|Registry for action types.|
1346+
|uiSettings|Optional property, which is needed to display visualization of alert type expression. Will be changed after visualization refactoring.|
1347+
|toastNotifications|Toast messages.|
1348+
|charts|Optional property, which is needed to display visualization of alert type expression. Will be changed after visualization refactoring.|
1349+
|dataFieldsFormats|Optional property, which is needed to display visualization of alert type expression. Will be changed after visualization refactoring.|
1350+
12071351
## Embed the Create Connector flyout within any Kibana plugin
12081352

12091353
Follow the instructions bellow to embed the Create Connector flyout within any Kibana plugin:
@@ -1413,3 +1557,4 @@ export interface ActionsConnectorsContextValue {
14131557
|capabilities|Property, which is defining action current user usage capabilities like canSave or canDelete.|
14141558
|toastNotifications|Toast messages.|
14151559
|reloadConnectors|Optional function, which will be executed if connector was saved sucsessfuly, like reload list of connecotrs.|
1560+

x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/email.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,14 +263,14 @@ const EmailActionConnectorFields: React.FunctionComponent<ActionConnectorFieldsP
263263
isInvalid={errors.port.length > 0 && port !== undefined}
264264
fullWidth
265265
name="port"
266-
value={port}
266+
value={port || ''}
267267
data-test-subj="emailPortInput"
268268
onChange={e => {
269269
editActionConfig('port', parseInt(e.target.value, 10));
270270
}}
271271
onBlur={() => {
272272
if (!port) {
273-
editActionConfig('port', '');
273+
editActionConfig('port', 0);
274274
}
275275
}}
276276
/>
@@ -380,7 +380,7 @@ const EmailParamsFields: React.FunctionComponent<ActionParamsProps<EmailActionPa
380380

381381
const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState<boolean>(false);
382382
useEffect(() => {
383-
if (defaultMessage && defaultMessage.length > 0) {
383+
if (!message && defaultMessage && defaultMessage.length > 0) {
384384
editAction('message', defaultMessage, index);
385385
}
386386
// eslint-disable-next-line react-hooks/exhaustive-deps

x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/server_log.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export const ServerLogParamsFields: React.FunctionComponent<ActionParamsProps<
7575

7676
useEffect(() => {
7777
editAction('level', 'info', index);
78-
if (defaultMessage && defaultMessage.length > 0) {
78+
if (!message && defaultMessage && defaultMessage.length > 0) {
7979
editAction('message', defaultMessage, index);
8080
}
8181
// eslint-disable-next-line react-hooks/exhaustive-deps

x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ const SlackParamsFields: React.FunctionComponent<ActionParamsProps<SlackActionPa
143143
const { message } = actionParams;
144144
const [isVariablesPopoverOpen, setIsVariablesPopoverOpen] = useState<boolean>(false);
145145
useEffect(() => {
146-
if (defaultMessage && defaultMessage.length > 0) {
146+
if (!message && defaultMessage && defaultMessage.length > 0) {
147147
editAction('message', defaultMessage, index);
148148
}
149149
// eslint-disable-next-line react-hooks/exhaustive-deps

x-pack/plugins/triggers_actions_ui/public/application/context/alerts_context.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@ export interface AlertsContextValue<MetaData = Record<string, any>> {
1616
http: HttpSetup;
1717
alertTypeRegistry: TypeRegistry<AlertTypeModel>;
1818
actionTypeRegistry: TypeRegistry<ActionTypeModel>;
19-
uiSettings?: IUiSettingsClient;
20-
toastNotifications?: Pick<
19+
toastNotifications: Pick<
2120
ToastsApi,
2221
'get$' | 'add' | 'remove' | 'addSuccess' | 'addWarning' | 'addDanger' | 'addError'
2322
>;
23+
uiSettings?: IUiSettingsClient;
2424
charts?: ChartsPluginSetup;
2525
dataFieldsFormats?: DataPublicPluginSetup['fieldFormats'];
2626
metadata?: MetaData;

0 commit comments

Comments
 (0)