diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira.tsx index 0179cfbffdfea..81f0bbfe8a02f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira.tsx @@ -27,8 +27,12 @@ const validateConnector = (action: JiraActionConnector): ValidationResult => { errors.apiUrl = [...errors.apiUrl, i18n.API_URL_REQUIRED]; } - if (action.config.apiUrl && !isValidUrl(action.config.apiUrl, 'https:')) { - errors.apiUrl = [...errors.apiUrl, i18n.API_URL_INVALID]; + if (action.config.apiUrl) { + if (!isValidUrl(action.config.apiUrl)) { + errors.apiUrl = [...errors.apiUrl, i18n.API_URL_INVALID]; + } else if (!isValidUrl(action.config.apiUrl, 'https:')) { + errors.apiUrl = [...errors.apiUrl, i18n.API_URL_REQUIRE_HTTPS]; + } } if (!action.config.projectKey) { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_connectors.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_connectors.tsx index 35c6bd7af00ab..64ae752afa901 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_connectors.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_connectors.tsx @@ -98,7 +98,6 @@ const JiraConnectorFields: React.FC handleOnChangeActionConfig('apiUrl', evt.target.value)} onBlur={() => { if (!apiUrl) { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/translations.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/translations.ts index f6db56e188322..6f45316ff4433 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/translations.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/translations.ts @@ -41,6 +41,13 @@ export const API_URL_INVALID = i18n.translate( } ); +export const API_URL_REQUIRE_HTTPS = i18n.translate( + 'xpack.triggersActionsUI.components.builtinActionTypes.jira.requireHttpsApiUrlTextField', + { + defaultMessage: 'URL must start with https://.', + } +); + export const JIRA_PROJECT_KEY_LABEL = i18n.translate( 'xpack.triggersActionsUI.components.builtinActionTypes.jira.projectKey', { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient.tsx index 1b27968c04fd3..6d57fc98fe20f 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient.tsx @@ -31,8 +31,12 @@ const validateConnector = (action: ResilientActionConnector): ValidationResult = errors.apiUrl = [...errors.apiUrl, i18n.API_URL_REQUIRED]; } - if (action.config.apiUrl && !isValidUrl(action.config.apiUrl, 'https:')) { - errors.apiUrl = [...errors.apiUrl, i18n.API_URL_INVALID]; + if (action.config.apiUrl) { + if (!isValidUrl(action.config.apiUrl)) { + errors.apiUrl = [...errors.apiUrl, i18n.API_URL_INVALID]; + } else if (!isValidUrl(action.config.apiUrl, 'https:')) { + errors.apiUrl = [...errors.apiUrl, i18n.API_URL_REQUIRE_HTTPS]; + } } if (!action.config.orgId) { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_connectors.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_connectors.tsx index fe2aa341a7111..68626e8a0d3fa 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_connectors.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_connectors.tsx @@ -98,7 +98,6 @@ const ResilientConnectorFields: React.FC handleOnChangeActionConfig('apiUrl', evt.target.value)} onBlur={() => { if (!apiUrl) { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/translations.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/translations.ts index b45f898d7d809..65d08c9f7de68 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/translations.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/translations.ts @@ -41,6 +41,13 @@ export const API_URL_INVALID = i18n.translate( } ); +export const API_URL_REQUIRE_HTTPS = i18n.translate( + 'xpack.triggersActionsUI.components.builtinActionTypes.resilient.requireHttpsApiUrlTextField', + { + defaultMessage: 'URL must start with https://.', + } +); + export const ORG_ID_LABEL = i18n.translate( 'xpack.triggersActionsUI.components.builtinActionTypes.resilient.orgId', { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.tsx index 8396497a6e284..9cc689d8f48b1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow.tsx @@ -30,8 +30,12 @@ const validateConnector = (action: ServiceNowActionConnector): ValidationResult errors.apiUrl = [...errors.apiUrl, i18n.API_URL_REQUIRED]; } - if (action.config.apiUrl && !isValidUrl(action.config.apiUrl, 'https:')) { - errors.apiUrl = [...errors.apiUrl, i18n.API_URL_INVALID]; + if (action.config.apiUrl) { + if (!isValidUrl(action.config.apiUrl)) { + errors.apiUrl = [...errors.apiUrl, i18n.API_URL_INVALID]; + } else if (!isValidUrl(action.config.apiUrl, 'https:')) { + errors.apiUrl = [...errors.apiUrl, i18n.API_URL_REQUIRE_HTTPS]; + } } if (!action.secrets.username) { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.tsx index d351b32c3bb06..66de29c68de2b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_connectors.tsx @@ -104,7 +104,6 @@ const ServiceNowConnectorFields: React.FC handleOnChangeActionConfig('apiUrl', evt.target.value)} onBlur={() => { if (!apiUrl) { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/translations.ts b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/translations.ts index 67e94bc136cf9..312cb9844bd75 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/translations.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/translations.ts @@ -41,6 +41,13 @@ export const API_URL_INVALID = i18n.translate( } ); +export const API_URL_REQUIRE_HTTPS = i18n.translate( + 'xpack.triggersActionsUI.components.builtinActionTypes.servicenow.requireHttpsApiUrlTextField', + { + defaultMessage: 'URL must start with https://.', + } +); + export const AUTHENTICATION_LABEL = i18n.translate( 'xpack.triggersActionsUI.components.builtinActionTypes.servicenow.authenticationLabel', { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack.test.tsx index 78f4161cac827..01343dcd472ce 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack.test.tsx @@ -31,11 +31,11 @@ describe('slack connector validation', () => { test('connector validation succeeds when connector config is valid', () => { const actionConnector = { secrets: { - webhookUrl: 'http:\\test', + webhookUrl: 'https:\\test', }, id: 'test', - actionTypeId: '.email', - name: 'email', + actionTypeId: '.slack', + name: 'slack', config: {}, } as SlackActionConnector; @@ -46,12 +46,12 @@ describe('slack connector validation', () => { }); }); - test('connector validation fails when connector config is not valid', () => { + test('connector validation fails when connector config is not valid - no webhook url', () => { const actionConnector = { secrets: {}, id: 'test', - actionTypeId: '.email', - name: 'email', + actionTypeId: '.slack', + name: 'slack', config: {}, } as SlackActionConnector; @@ -61,6 +61,42 @@ describe('slack connector validation', () => { }, }); }); + + test('connector validation fails when connector config is not valid - invalid webhook protocol', () => { + const actionConnector = { + secrets: { + webhookUrl: 'http:\\test', + }, + id: 'test', + actionTypeId: '.slack', + name: 'slack', + config: {}, + } as SlackActionConnector; + + expect(actionTypeModel.validateConnector(actionConnector)).toEqual({ + errors: { + webhookUrl: ['Webhook URL must start with https://.'], + }, + }); + }); + + test('connector validation fails when connector config is not valid - invalid webhook url', () => { + const actionConnector = { + secrets: { + webhookUrl: 'h', + }, + id: 'test', + actionTypeId: '.slack', + name: 'slack', + config: {}, + } as SlackActionConnector; + + expect(actionTypeModel.validateConnector(actionConnector)).toEqual({ + errors: { + webhookUrl: ['Webhook URL is invalid.'], + }, + }); + }); }); describe('slack action params validation', () => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack.tsx index 23c76f327008b..1df78b4c9312d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/slack/slack.tsx @@ -7,6 +7,7 @@ import { lazy } from 'react'; import { i18n } from '@kbn/i18n'; import { ActionTypeModel, ValidationResult } from '../../../../types'; import { SlackActionParams, SlackSecrets, SlackActionConnector } from '../types'; +import { isValidUrl } from '../../../lib/value_validators'; export function getActionType(): ActionTypeModel { return { @@ -39,6 +40,26 @@ export function getActionType(): ActionTypeModel 0 && webhookUrl !== undefined} name="webhookUrl" readOnly={readOnly} - placeholder="Example: https://hooks.slack.com/services" value={webhookUrl || ''} data-test-subj="slackWebhookUrlInput" onChange={(e) => { diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_connectors.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_connectors.tsx index 15d4c6c30450e..1a9de48ccce3a 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_connectors.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/webhook/webhook_connectors.tsx @@ -261,7 +261,6 @@ const WebhookActionConnectorFields: React.FunctionComponent { editActionConfig('url', e.target.value);