From bd2e08787efa9468b3b0a1c2523305d53ba31e79 Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Mon, 6 Jul 2020 17:35:47 -0700 Subject: [PATCH] Added UI validation when creating a Webhook connector with invalid URL (#70025) * Added UI validation when creating a Webhook connector with invalid URL * fixed tests * Fixed due to comments * fixed type check and extended error message for invalid URL * Fixed whitelisting of URL * fixed failing tests * fixed str --- .../builtin_action_types/webhook.test.ts | 11 ++++++++ .../server/builtin_action_types/webhook.ts | 14 +++++++++- .../webhook/webhook.test.tsx | 27 ++++++++++++++++++- .../builtin_action_types/webhook/webhook.tsx | 12 +++++++++ .../webhook/webhook_connectors.tsx | 1 + 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts index 6daf15208f4d9..53b17f58d6e18 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.test.ts @@ -114,6 +114,17 @@ describe('config validation', () => { }); }); + test('config validation failed when a url is invalid', () => { + const config: Record = { + url: 'example.com/do-something', + }; + expect(() => { + validateConfig(actionType, config); + }).toThrowErrorMatchingInlineSnapshot( + '"error validating action type config: error configuring webhook action: unable to parse url: TypeError: Invalid URL: example.com/do-something"' + ); + }); + test('config validation passes when valid headers are provided', () => { // any for testing // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts index 4a34fea762164..0b8b27b278928 100644 --- a/x-pack/plugins/actions/server/builtin_action_types/webhook.ts +++ b/x-pack/plugins/actions/server/builtin_action_types/webhook.ts @@ -85,8 +85,20 @@ function validateActionTypeConfig( configurationUtilities: ActionsConfigurationUtilities, configObject: ActionTypeConfigType ) { + let url: URL; try { - configurationUtilities.ensureWhitelistedUri(configObject.url); + url = new URL(configObject.url); + } catch (err) { + return i18n.translate('xpack.actions.builtin.webhook.webhookConfigurationErrorNoHostname', { + defaultMessage: 'error configuring webhook action: unable to parse url: {err}', + values: { + err, + }, + }); + } + + try { + configurationUtilities.ensureWhitelistedUri(url.toString()); } catch (whitelistError) { return i18n.translate('xpack.actions.builtin.webhook.webhookConfigurationError', { defaultMessage: 'error configuring webhook action: {message}', diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook.test.tsx index 3413465d70d93..337c1f0f18a93 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook.test.tsx @@ -40,7 +40,7 @@ describe('webhook connector validation', () => { isPreconfigured: false, config: { method: 'PUT', - url: 'http:\\test', + url: 'http://test.com', headers: { 'content-type': 'text' }, }, } as WebhookActionConnector; @@ -77,6 +77,31 @@ describe('webhook connector validation', () => { }, }); }); + + test('connector validation fails when url in config is not valid', () => { + const actionConnector = { + secrets: { + user: 'user', + password: 'pass', + }, + id: 'test', + actionTypeId: '.webhook', + name: 'webhook', + config: { + method: 'PUT', + url: 'invalid.url', + }, + } as WebhookActionConnector; + + expect(actionTypeModel.validateConnector(actionConnector)).toEqual({ + errors: { + url: ['URL is invalid.'], + method: [], + user: [], + password: [], + }, + }); + }); }); describe('webhook action params validation', () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook.tsx index 9f33e4491233a..2c51b21d70034 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook.tsx @@ -7,6 +7,7 @@ import { lazy } from 'react'; import { i18n } from '@kbn/i18n'; import { ActionTypeModel, ValidationResult } from '../../../../types'; import { WebhookActionParams, WebhookActionConnector } from '../types'; +import { isValidUrl } from '../../../lib/value_validators'; export function getActionType(): ActionTypeModel { return { @@ -43,6 +44,17 @@ export function getActionType(): ActionTypeModel 0 && url !== undefined} fullWidth value={url || ''} + placeholder="https:// or http://" data-test-subj="webhookUrlText" onChange={(e) => { editActionConfig('url', e.target.value);