Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] [Detections] Adds support for system actions (and cases action) to detection rules #183937

Merged
merged 74 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
2cfed78
working system actions for cases for create rule route security
dhurley14 May 21, 2024
a2bb5ba
merge with main
dhurley14 Jun 17, 2024
7082de6
fix merge conflict, re-delete file
dhurley14 Jun 17, 2024
5e137b3
create rule with system actions cases works after the rules client re…
dhurley14 Jun 17, 2024
3600f32
isntantiate actions client within detection rules client
dhurley14 Jun 19, 2024
7140b48
Merge branch 'main' into system-actions-security
dhurley14 Jun 19, 2024
33cebd7
Merge branch 'main' into system-actions-security
dhurley14 Jun 19, 2024
2a91ec0
Merge branch 'main' into system-actions-security
dhurley14 Jun 19, 2024
4d73f76
working rule export
dhurley14 Jun 25, 2024
2ef4df5
import rule with system action working
dhurley14 Jun 25, 2024
62b6ec8
adds support for update with system actions
dhurley14 Jun 25, 2024
67e406b
adds support for system actions in patch, cleanup types
dhurley14 Jun 26, 2024
5e61574
small fix with partition logic
dhurley14 Jun 26, 2024
7c72634
small cleanup and notes for cleanup / investigation tomorrow
dhurley14 Jun 27, 2024
7f7a4ba
remove unused import
dhurley14 Jun 27, 2024
098194d
small updates and cleanup
dhurley14 Jun 27, 2024
fdce619
fixes duplicate rule unit tests
dhurley14 Jun 27, 2024
8d75153
fixes createCustomeRule unit test
dhurley14 Jun 27, 2024
0599aa2
fixes unit test mocks for detection rules client
dhurley14 Jun 27, 2024
3c8a799
fixes types on UI
dhurley14 Jun 27, 2024
1d02e49
partition on action.id, not action_type_id
dhurley14 Jun 28, 2024
0b121bd
merge with main
dhurley14 Jun 28, 2024
b697826
fixes duplicate rule with system actions
dhurley14 Jun 28, 2024
43a779f
fixes duplicate rule functionality
dhurley14 Jun 28, 2024
ed4b400
updates tests, render cases title for system action on rule details page
dhurley14 Jun 28, 2024
033fe41
removes console statements
dhurley14 Jul 1, 2024
b3f5498
remove comment
dhurley14 Jul 1, 2024
caa8702
more cleanup
dhurley14 Jul 1, 2024
73202f0
Merge remote-tracking branch 'upstream/main' into system-actions-secu…
dhurley14 Jul 1, 2024
6a6f397
Merge branch 'main' into system-actions-security
dhurley14 Jul 2, 2024
6e16ab0
Merge remote-tracking branch 'upstream/main' into system-actions-secu…
dhurley14 Jul 2, 2024
1b35aeb
fixes issue where if actions were not present in the update (i.e. pat…
dhurley14 Jul 2, 2024
9eeb2e6
remove test cases looking for 'group' property, updates actionsClient…
dhurley14 Jul 2, 2024
56c8b03
Merge branch 'main' into system-actions-security
dhurley14 Jul 2, 2024
06efd06
Merge branch 'main' into system-actions-security
dhurley14 Jul 2, 2024
c250336
remove hardcoded string value for siem feature id in cases action
dhurley14 Jul 3, 2024
dfb239e
updates rules client to use named parameters
dhurley14 Jul 3, 2024
1fbafc3
named params in context factor, adds test for migrate legacy actions,…
dhurley14 Jul 3, 2024
0e42109
fix mistyped parameter for rule create / edit form
dhurley14 Jul 3, 2024
7254095
adds tests for validating changes made to convertCreateAPIToInternalS…
dhurley14 Jul 3, 2024
77e351b
fixes create_custom_rule test mock
dhurley14 Jul 3, 2024
0e4f045
updates detection rules client patch and update() unit tests
dhurley14 Jul 3, 2024
683504b
make system actions optional on the internal create and update types
dhurley14 Jul 3, 2024
57a4a77
adds wrappers around partition and array.map -> transformRuleToAlertA…
dhurley14 Jul 3, 2024
e36a295
adds FTR test which creates a rule and case system action and checks …
dhurley14 Jul 3, 2024
ed6f8c7
forgot to add the actual test case
dhurley14 Jul 5, 2024
69ba82b
fixes rule edit bulk actions -> set and add actions
dhurley14 Jul 5, 2024
475915e
fixes tests and type checker
dhurley14 Jul 5, 2024
3b8e874
Merge remote-tracking branch 'upstream/main' into system-actions-secu…
dhurley14 Jul 5, 2024
bf2d39b
undo ftr test
dhurley14 Jul 9, 2024
9e8eda5
merge with main
dhurley14 Jul 15, 2024
9e67428
Merge remote-tracking branch 'upstream/main' into system-actions-secu…
dhurley14 Jul 15, 2024
5827e1e
change boolean name and import, move ftr test to actions
dhurley14 Jul 16, 2024
ee5ae09
Merge remote-tracking branch 'upstream/main' into system-actions-secu…
dhurley14 Jul 16, 2024
cc33a01
adds condition in cypress test to ensure complete tier cases action i…
dhurley14 Jul 16, 2024
dbf4db2
fix unit tests
dhurley14 Jul 17, 2024
991e10a
fixes ftr test for adding case system action to rule
dhurley14 Jul 17, 2024
374309c
undo before and after fn changes from testing
dhurley14 Jul 17, 2024
da2217f
Merge remote-tracking branch 'upstream/main' into system-actions-secu…
dhurley14 Jul 18, 2024
fee7dbb
remove unused function
dhurley14 Jul 18, 2024
bd7c725
adds comment to logic in notification action component
dhurley14 Jul 18, 2024
604a755
[CI] Auto-commit changed files from 'yarn openapi:bundle'
kibanamachine Jul 18, 2024
bc9efa2
merge with main
dhurley14 Jul 19, 2024
09716a2
Merge branch 'system-actions-security' of github.com:dhurley14/kibana…
dhurley14 Jul 19, 2024
f2e919d
merge with main
dhurley14 Jul 24, 2024
8de96fa
Update x-pack/plugins/security_solution/public/detection_engine/rule_…
dhurley14 Jul 24, 2024
19748e3
adds check to ensure cases action is visible in serverless complete tier
dhurley14 Jul 24, 2024
851e19a
move function parameters so actionsClient is last
dhurley14 Jul 24, 2024
3848196
adds unit tests for changes to bulkEditActionToRulesClientOperation
dhurley14 Jul 24, 2024
8d517b4
fixes prettier problem from code suggestion commit in github
dhurley14 Jul 24, 2024
739a6a3
Merge branch 'main' into system-actions-security
dhurley14 Jul 25, 2024
3903f00
adds frequency message for cases system action
dhurley14 Jul 25, 2024
872477e
Merge branch 'system-actions-security' of github.com:dhurley14/kibana…
dhurley14 Jul 26, 2024
256b6ea
remove comment, delete whitespace
dhurley14 Jul 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions x-pack/plugins/cases/server/connectors/cases/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
* 2.0.
*/

import { AlertingConnectorFeatureId, UptimeConnectorFeatureId } from '@kbn/actions-plugin/common';
import {
AlertingConnectorFeatureId,
UptimeConnectorFeatureId,
SecurityConnectorFeatureId,
} from '@kbn/actions-plugin/common';
import type { SubActionConnectorType } from '@kbn/actions-plugin/server/sub_action_framework/types';
import type { KibanaRequest } from '@kbn/core-http-server';
import type { SavedObjectsClientContract } from '@kbn/core/server';
Expand Down Expand Up @@ -56,7 +60,11 @@ export const getCasesConnectorType = ({
config: CasesConnectorConfigSchema,
secrets: CasesConnectorSecretsSchema,
},
supportedFeatureIds: [UptimeConnectorFeatureId, AlertingConnectorFeatureId],
supportedFeatureIds: [
UptimeConnectorFeatureId,
AlertingConnectorFeatureId,
SecurityConnectorFeatureId,
],
minimumLicenseRequired: 'platinum' as const,
isSystemActionType: true,
getKibanaPrivileges: ({ params } = { params: { subAction: 'run', subActionParams: {} } }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ export const RuleAction = z.object({
* The action type used for sending notifications.
*/
action_type_id: z.string(),
group: RuleActionGroup,
group: RuleActionGroup.optional(),
id: RuleActionId,
params: RuleActionParams,
uuid: NonEmptyString.optional(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,6 @@ components:
$ref: '#/components/schemas/RuleActionFrequency'
required:
- action_type_id
- group
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For any questions on this, I pulled this from the system actions RFC:

All rules APIs will not accept the systemActions in their requests. The system will deduct if an action is a system action automatically using the actions’ client. As system actions are not allowed to have a group, the property will be optional (at the moment it is required) in all APIs. The APIs will convert the actions to the schema needed by the rules client. Finally, the APIs will merge the system actions with the default actions before sending the response back to the client.

Ref: https://docs.google.com/document/d/1mYStNLxrafnyxR6v_uB4ONw_iFHTg1pmE3EAQYgKFSY/edit?pli=1

- id
- params

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -719,17 +719,6 @@ describe('rules schema', () => {
);
});

test('You cannot send in an array of actions that are missing "group"', () => {
const payload = {
...getCreateRulesSchemaMock(),
actions: [{ id: 'id', action_type_id: 'action_type_id', params: {} }],
};

const result = RuleCreateProps.safeParse(payload);
expectParseError(result);
expect(stringifyZodError(result.error)).toEqual('actions.0.group: Required');
});

test('You cannot send in an array of actions that are missing "id"', () => {
const payload = {
...getCreateRulesSchemaMock(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ export const BulkActionEditTypeEnum = BulkActionEditType.enum;
export type NormalizedRuleAction = z.infer<typeof NormalizedRuleAction>;
export const NormalizedRuleAction = z
.object({
group: RuleActionGroup,
group: RuleActionGroup.optional(),
id: RuleActionId,
params: RuleActionParams,
frequency: RuleActionFrequency.optional(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,6 @@ components:
alerts_filter:
$ref: '../../model/rule_schema/common_attributes.schema.yaml#/components/schemas/RuleActionAlertsFilter'
required:
- group
- id
- params
additionalProperties: false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -766,19 +766,6 @@ describe('Patch rule request schema', () => {
});
});

test('You cannot send in an array of actions that are missing "group"', () => {
const payload: Omit<PatchRuleRequestBody['actions'], 'group'> = {
...getPatchRulesSchemaMock(),
actions: [{ id: 'id', action_type_id: 'action_type_id', params: {} }],
};

const result = PatchRuleRequestBody.safeParse(payload);
expectParseError(result);
expect(stringifyZodError(result.error)).toMatchInlineSnapshot(
`"actions.0.group: Required, type: Invalid literal value, expected \\"eql\\", language: Invalid literal value, expected \\"eql\\", actions.0.group: Required, actions.0.group: Required, and 12 more"`
);
});

test('You cannot send in an array of actions that are missing "id"', () => {
const payload: Omit<PatchRuleRequestBody['actions'], 'id'> = {
...getPatchRulesSchemaMock(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -776,20 +776,6 @@ describe('RuleToImport', () => {
expectParseSuccess(result);
});

test('You cannot send in an array of actions that are missing "group"', () => {
const payload = getImportRulesSchemaMock({
actions: [
// @ts-expect-error assign unsupported value
{ id: 'id', action_type_id: 'action_type_id', params: {} },
],
});

const result = RuleToImport.safeParse(payload);
expectParseError(result);

expect(stringifyZodError(result.error)).toMatchInlineSnapshot(`"actions.0.group: Required"`);
});

test('You cannot send in an array of actions that are missing "id"', () => {
const payload = getImportRulesSchemaMock({
actions: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@
* 2.0.
*/

import type { RuleAction as AlertingRuleAction } from '@kbn/alerting-plugin/common';
import type { NormalizedAlertAction } from '@kbn/alerting-plugin/server/rules_client';
import type {
RuleAction as AlertingRuleAction,
RuleSystemAction as AlertingRuleSystemAction,
} from '@kbn/alerting-plugin/common';
import type {
NormalizedAlertAction,
NormalizedSystemAction,
} from '@kbn/alerting-plugin/server/rules_client';
import type { NormalizedRuleAction } from '../api/detection_engine/rule_management';
import type {
ResponseAction,
Expand All @@ -23,8 +29,7 @@ export const transformRuleToAlertAction = ({
uuid,
frequency,
alerts_filter: alertsFilter,
}: RuleAction): AlertingRuleAction => ({
group,
}: RuleAction): AlertingRuleAction | AlertingRuleSystemAction => ({
id,
params: params as AlertingRuleAction['params'],
actionTypeId,
Expand All @@ -33,6 +38,7 @@ export const transformRuleToAlertAction = ({
}),
...(uuid && { uuid }),
...(frequency && { frequency }),
...(group && { group }),
});

export const transformAlertToRuleAction = ({
Expand All @@ -44,13 +50,25 @@ export const transformAlertToRuleAction = ({
frequency,
alertsFilter,
}: AlertingRuleAction): RuleAction => ({
group,
id,
params,
action_type_id: actionTypeId,
...(alertsFilter && { alerts_filter: alertsFilter }),
...(uuid && { uuid }),
...(frequency && { frequency }),
...(group && { group }),
});

export const transformAlertToRuleSystemAction = ({
id,
actionTypeId,
params,
uuid,
}: AlertingRuleSystemAction): RuleAction => ({
id,
params,
action_type_id: actionTypeId,
...(uuid && { uuid }),
});

export const transformNormalizedRuleToAlertAction = ({
Expand All @@ -59,8 +77,7 @@ export const transformNormalizedRuleToAlertAction = ({
params,
frequency,
alerts_filter: alertsFilter,
}: NormalizedRuleAction): NormalizedAlertAction => ({
group,
}: NormalizedRuleAction): NormalizedAlertAction | NormalizedSystemAction => ({
id,
params: params as AlertingRuleAction['params'],
...(alertsFilter && {
Expand All @@ -70,6 +87,7 @@ export const transformNormalizedRuleToAlertAction = ({
alertsFilter: alertsFilter as AlertingRuleAction['alertsFilter'],
}),
...(frequency && { frequency }),
...(group && { group }),
});

export const transformAlertToNormalizedRuleAction = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4104,7 +4104,6 @@ components:
params:
$ref: '#/components/schemas/RuleActionParams'
required:
- group
- id
- params
NormalizedRuleError:
Expand Down Expand Up @@ -4902,7 +4901,6 @@ components:
$ref: '#/components/schemas/NonEmptyString'
required:
- action_type_id
- group
- id
- params
RuleActionAlertsFilter:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3272,7 +3272,6 @@ components:
params:
$ref: '#/components/schemas/RuleActionParams'
required:
- group
- id
- params
NormalizedRuleError:
Expand Down Expand Up @@ -4070,7 +4069,6 @@ components:
$ref: '#/components/schemas/NonEmptyString'
required:
- action_type_id
- group
- id
- params
RuleActionAlertsFilter:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@ import React from 'react';
import { EuiToolTip, EuiText, EuiSpacer, EuiFlexGroup, EuiFlexItem, EuiIcon } from '@elastic/eui';
import type { ActionType, AsApiContract } from '@kbn/actions-plugin/common';
import type { ActionResult } from '@kbn/actions-plugin/server';
import type { RuleActionFrequency, RuleAction } from '@kbn/alerting-plugin/common';
import type {
RuleActionFrequency,
RuleAction,
RuleSystemAction,
} from '@kbn/alerting-plugin/common';
import type { ActionTypeRegistryContract } from '@kbn/triggers-actions-ui-plugin/public';
import { FormattedMessage } from '@kbn/i18n-react';
import { getTimeTypeValue } from '../../../rule_creation_ui/pages/rule_creation/helpers';
import {
getTimeTypeValue,
isRuleAction as getIsRuleAction,
} from '../../../rule_creation_ui/pages/rule_creation/helpers';
import * as i18n from './translations';

const DescriptionLine = ({ children }: { children: React.ReactNode }) => (
Expand Down Expand Up @@ -79,7 +86,7 @@ export const FrequencyDescription: React.FC<{ frequency?: RuleActionFrequency }>
};

interface NotificationActionProps {
action: RuleAction;
action: RuleAction | RuleSystemAction;
connectorTypes: ActionType[];
connectors: Array<AsApiContract<ActionResult>>;
actionTypeRegistry: ActionTypeRegistryContract;
Expand All @@ -91,13 +98,23 @@ export function NotificationAction({
connectors,
actionTypeRegistry,
}: NotificationActionProps) {
const isRuleAction = getIsRuleAction(action, actionTypeRegistry);
const connectorType = connectorTypes.find(({ id }) => id === action.actionTypeId);
const connectorTypeName = connectorType?.name ?? '';
const registeredAction = actionTypeRegistry.get(action.actionTypeId);

const connector = connectors.find(({ id }) => id === action.id);
const connectorName = connector?.name ?? '';
/*
since there is no "connector" for system actions,
we need to determine the title based off the action
properties in order to render helpful text on the
rule details page.
*/
const connectorTypeName = isRuleAction
? connectorType?.name ?? ''
: registeredAction.actionTypeTitle ?? '';
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since there is no "connector" for system actions, we need to determine the title based off the action properties in order to render helpful text on the rule details page.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add this as comment here? Or even better, extract the logic out to a function and explain it there.

const iconType = registeredAction?.iconClass ?? 'apps';

const iconType = actionTypeRegistry.get(action.actionTypeId)?.iconClass ?? 'apps';
const connector = connectors.find(({ id }) => id === action.id);
const connectorName = (isRuleAction ? connector?.name : registeredAction.actionTypeTitle) ?? '';

return (
<EuiFlexItem>
Expand All @@ -114,7 +131,13 @@ export function NotificationAction({
<EuiFlexItem grow={false}>
<EuiIcon size="s" type="bell" color="subdued" />
</EuiFlexItem>
<FrequencyDescription frequency={action.frequency} />
{isRuleAction ? (
<FrequencyDescription frequency={action.frequency} />
) : (
// Display frequency description for system action
// same text used by stack alerting
<DescriptionLine>{i18n.SYSTEM_ACTION_FREQUENCY}</DescriptionLine>
)}
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,8 @@ export const PERIODICALLY = i18n.translate(
'xpack.securitySolution.detectionEngine.actionNotifyWhen.periodically',
{ defaultMessage: 'Periodically' }
);

export const SYSTEM_ACTION_FREQUENCY = i18n.translate(
'xpack.securitySolution.detectionEngine.actionNotifyWhen.systemActionFrequency',
{ defaultMessage: 'On check intervals' }
);
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
ScheduleStepRule,
TimeframePreviewOptions,
} from '../../../../detections/pages/detection_engine/rules/types';
import { useKibana } from '../../../../common/lib/kibana';

interface PreviewRouteParams {
defineRuleData?: DefineStepRule;
Expand All @@ -34,6 +35,10 @@ export const usePreviewRoute = ({
}: PreviewRouteParams) => {
const [isRequestTriggered, setIsRequestTriggered] = useState(false);

const {
triggersActionsUi: { actionTypeRegistry },
} = useKibana().services;

const { isLoading, response, rule, setRule } = usePreviewRule({
timeframeOptions,
});
Expand Down Expand Up @@ -72,6 +77,7 @@ export const usePreviewRoute = ({
defineRuleData,
aboutRuleData,
scheduleRuleData,
actionTypeRegistry,
exceptionsList,
})
);
Expand All @@ -84,6 +90,7 @@ export const usePreviewRoute = ({
aboutRuleData,
scheduleRuleData,
exceptionsList,
actionTypeRegistry,
]);

return {
Expand Down
Loading