Skip to content

Commit

Permalink
fixed validation usage in security
Browse files Browse the repository at this point in the history
  • Loading branch information
YulNaumenko committed May 27, 2021
1 parent 8021eed commit 0d1fe6a
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const StepRuleActionsComponent: FC<StepRuleActionsProps> = ({
...(defaultValues ?? stepActionsDefaultValue),
kibanaSiemAppUrl: kibanaAbsoluteUrl,
};

const schema = useMemo(() => getSchema({ actionTypeRegistry }), [actionTypeRegistry]);
const { form } = useForm<ActionsStepRule>({
defaultValue: initialState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ describe('stepRuleActions schema', () => {
const actionTypeRegistry = actionTypeRegistryMock.create();

describe('validateSingleAction', () => {
it('should validate single action', () => {
it('should validate single action', async () => {
(isUuid as jest.Mock).mockReturnValue(true);
(validateActionParams as jest.Mock).mockReturnValue([]);
(validateMustache as jest.Mock).mockReturnValue([]);

expect(
validateSingleAction(
await validateSingleAction(
{
id: '817b8bca-91d1-4729-8ee1-3a83aaafd9d4',
group: 'default',
Expand All @@ -33,12 +33,12 @@ describe('stepRuleActions schema', () => {
).toHaveLength(0);
});

it('should validate single action with invalid mustache template', () => {
it('should validate single action with invalid mustache template', async () => {
(isUuid as jest.Mock).mockReturnValue(true);
(validateActionParams as jest.Mock).mockReturnValue([]);
(validateMustache as jest.Mock).mockReturnValue(['Message is not valid mustache template']);

const errors = validateSingleAction(
const errors = await validateSingleAction(
{
id: '817b8bca-91d1-4729-8ee1-3a83aaafd9d4',
group: 'default',
Expand All @@ -54,12 +54,12 @@ describe('stepRuleActions schema', () => {
expect(errors[0]).toEqual('Message is not valid mustache template');
});

it('should validate single action with incorrect id', () => {
it('should validate single action with incorrect id', async () => {
(isUuid as jest.Mock).mockReturnValue(false);
(validateMustache as jest.Mock).mockReturnValue([]);
(validateActionParams as jest.Mock).mockReturnValue([]);

const errors = validateSingleAction(
const errors = await validateSingleAction(
{
id: '823d4',
group: 'default',
Expand All @@ -74,10 +74,10 @@ describe('stepRuleActions schema', () => {
});

describe('validateRuleActionsField', () => {
it('should validate rule actions field', () => {
it('should validate rule actions field', async () => {
const validator = validateRuleActionsField(actionTypeRegistry);

const result = validator({
const result = await validator({
path: '',
value: [],
form: {} as FormHook,
Expand All @@ -88,11 +88,11 @@ describe('stepRuleActions schema', () => {
expect(result).toEqual(undefined);
});

it('should validate incorrect rule actions field', () => {
it('should validate incorrect rule actions field', async () => {
(getActionTypeName as jest.Mock).mockReturnValue('Slack');
const validator = validateRuleActionsField(actionTypeRegistry);

const result = validator({
const result = await validator({
path: '',
value: [
{
Expand All @@ -117,7 +117,7 @@ describe('stepRuleActions schema', () => {
});
});

it('should validate multiple incorrect rule actions field', () => {
it('should validate multiple incorrect rule actions field', async () => {
(isUuid as jest.Mock).mockReturnValueOnce(false);
(getActionTypeName as jest.Mock).mockReturnValueOnce('Slack');
(isUuid as jest.Mock).mockReturnValueOnce(true);
Expand All @@ -126,7 +126,7 @@ describe('stepRuleActions schema', () => {
(validateMustache as jest.Mock).mockReturnValue(['Component is not valid mustache template']);
const validator = validateRuleActionsField(actionTypeRegistry);

const result = validator({
const result = await validator({
path: '',
value: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,42 +13,47 @@ import {
AlertAction,
ActionTypeRegistryContract,
} from '../../../../../../triggers_actions_ui/public';
import { FormSchema, ValidationFunc, ERROR_CODE } from '../../../../shared_imports';
import {
FormSchema,
ValidationFunc,
ERROR_CODE,
ValidationError,
} from '../../../../shared_imports';
import { ActionsStepRule } from '../../../pages/detection_engine/rules/types';
import * as I18n from './translations';
import { isUuid, getActionTypeName, validateMustache, validateActionParams } from './utils';

export const validateSingleAction = (
export const validateSingleAction = async (
actionItem: AlertAction,
actionTypeRegistry: ActionTypeRegistryContract
): string[] => {
): Promise<string[]> => {
if (!isUuid(actionItem.id)) {
return [I18n.NO_CONNECTOR_SELECTED];
}

const actionParamsErrors = validateActionParams(actionItem, actionTypeRegistry);
const actionParamsErrors = await validateActionParams(actionItem, actionTypeRegistry);
const mustacheErrors = validateMustache(actionItem.params);

return [...actionParamsErrors, ...mustacheErrors];
};

export const validateRuleActionsField = (actionTypeRegistry: ActionTypeRegistryContract) => (
export const validateRuleActionsField = (actionTypeRegistry: ActionTypeRegistryContract) => async (
...data: Parameters<ValidationFunc>
): ReturnType<ValidationFunc<{}, ERROR_CODE>> | undefined => {
): Promise<ValidationError<ERROR_CODE> | void | undefined> => {
const [{ value, path }] = data as [{ value: AlertAction[]; path: string }];

const errors = value.reduce((acc, actionItem) => {
const errorsArray = validateSingleAction(actionItem, actionTypeRegistry);
const errors = await value.reduce(async (acc, actionItem) => {
const errorsArray = await validateSingleAction(actionItem, actionTypeRegistry);

if (errorsArray.length) {
const actionTypeName = getActionTypeName(actionItem.actionTypeId);
const errorsListItems = errorsArray.map((error) => `* ${error}\n`);

return [...acc, `\n**${actionTypeName}:**\n${errorsListItems.join('')}`];
return [...(await acc), `\n**${actionTypeName}:**\n${errorsListItems.join('')}`];
}

return acc;
}, [] as string[]);
}, Promise.resolve([] as string[]));

if (errors.length) {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ describe('stepRuleActions utils', () => {
actionTypeRegistry.get.mockReturnValue(actionMock);
});

it('should validate action params', () => {
it('should validate action params', async () => {
validateParamsMock.mockReturnValue({ errors: [] });

expect(
validateActionParams(
await validateActionParams(
{
id: '817b8bca-91d1-4729-8ee1-3a83aaafd9d4',
group: 'default',
Expand All @@ -79,13 +79,13 @@ describe('stepRuleActions utils', () => {
).toHaveLength(0);
});

it('should validate incorrect action params', () => {
it('should validate incorrect action params', async () => {
validateParamsMock.mockReturnValue({
errors: ['Message is required'],
});

expect(
validateActionParams(
await validateActionParams(
{
id: '817b8bca-91d1-4729-8ee1-3a83aaafd9d4',
group: 'default',
Expand All @@ -97,7 +97,7 @@ describe('stepRuleActions utils', () => {
).toHaveLength(1);
});

it('should validate incorrect action params and filter error objects', () => {
it('should validate incorrect action params and filter error objects', async () => {
validateParamsMock.mockReturnValue({
errors: [
{
Expand All @@ -107,7 +107,7 @@ describe('stepRuleActions utils', () => {
});

expect(
validateActionParams(
await validateActionParams(
{
id: '817b8bca-91d1-4729-8ee1-3a83aaafd9d4',
group: 'default',
Expand All @@ -119,13 +119,13 @@ describe('stepRuleActions utils', () => {
).toHaveLength(0);
});

it('should validate incorrect action params and filter duplicated errors', () => {
it('should validate incorrect action params and filter duplicated errors', async () => {
validateParamsMock.mockReturnValue({
errors: ['Message is required', 'Message is required', 'Message is required'],
});

expect(
validateActionParams(
await validateActionParams(
{
id: '817b8bca-91d1-4729-8ee1-3a83aaafd9d4',
group: 'default',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,11 @@ export const validateMustache = (params: AlertAction['params']) => {
return errors;
};

export const validateActionParams = (
export const validateActionParams = async (
actionItem: AlertAction,
actionTypeRegistry: ActionTypeRegistryContract
): string[] => {
const actionErrors = actionTypeRegistry
): Promise<string[]> => {
const actionErrors = await actionTypeRegistry
.get(actionItem.actionTypeId)
?.validateParams(actionItem.params);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import React, { Fragment, useState, useEffect, useCallback } from 'react';
import React, { useState, useEffect, useCallback } from 'react';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import { TestConnectorForm } from './test_connector_form';
import {
ActionConnector,
ConnectorEditFlyoutProps,
ActionTypeRegistryContract,
IErrorObject,
EditConectorTabs,
UserConfiguredActionConnector,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,7 @@ import {
} from '@elastic/eui';
import { cloneDeep } from 'lodash';
import { i18n } from '@kbn/i18n';
import {
ActionTypeRegistryContract,
Alert,
AlertFlyoutCloseReason,
AlertTypeRegistryContract,
IErrorObject,
} from '../../../types';
import { Alert, AlertFlyoutCloseReason, AlertEditProps, IErrorObject } from '../../../types';
import { AlertForm, getAlertActionErrors, getAlertErrors, isValidAlert } from './alert_form';
import { alertReducer, ConcreteAlertReducer } from './alert_reducer';
import { updateAlert } from '../../lib/alert_api';
Expand Down

0 comments on commit 0d1fe6a

Please sign in to comment.