From 9a1f3a53be23706e9aa8087ddd2641993125e7ca Mon Sep 17 00:00:00 2001 From: Yuliia Naumenko Date: Wed, 5 Aug 2020 19:22:10 -0700 Subject: [PATCH] Migrated last pieces of legacy fixture code --- .../actions_simulators/server/plugin.ts | 21 +++- .../server/slack_simulation.ts | 79 ++++++++++++ .../server/webhook_simulation.ts | 83 +++++++++++++ .../actions_simulators_legacy/index.ts | 26 ---- .../actions_simulators_legacy/package.json | 7 -- .../slack_simulation.ts | 74 ------------ .../webhook_simulation.ts | 112 ------------------ .../actions/builtin_action_types/webhook.ts | 4 +- 8 files changed, 181 insertions(+), 225 deletions(-) create mode 100644 x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/slack_simulation.ts create mode 100644 x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/webhook_simulation.ts delete mode 100644 x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/index.ts delete mode 100644 x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/package.json delete mode 100644 x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/slack_simulation.ts delete mode 100644 x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/webhook_simulation.ts diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/plugin.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/plugin.ts index cb1271494c294..c1e45d4366178 100644 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/plugin.ts +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/plugin.ts @@ -4,6 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ +import http from 'http'; import { Plugin, CoreSetup, IRouter } from 'kibana/server'; import { EncryptedSavedObjectsPluginStart } from '../../../../../../../plugins/encrypted_saved_objects/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../../../../../../plugins/features/server'; @@ -13,6 +14,8 @@ import { initPlugin as initPagerduty } from './pagerduty_simulation'; import { initPlugin as initServiceNow } from './servicenow_simulation'; import { initPlugin as initJira } from './jira_simulation'; import { initPlugin as initResilient } from './resilient_simulation'; +import { initPlugin as initSlack } from './slack_simulation'; +import { initPlugin as initWebhook } from './webhook_simulation'; export const NAME = 'actions-FTS-external-service-simulators'; @@ -49,7 +52,9 @@ interface FixtureStartDeps { } export class FixturePlugin implements Plugin { - public setup(core: CoreSetup, { features, actions }: FixtureSetupDeps) { + private webhookHttpServer: http.Server | undefined = undefined; + + public async setup(core: CoreSetup, { features, actions }: FixtureSetupDeps) { // this action is specifically NOT enabled in ../../config.ts const notEnabledActionType: ActionType = { id: 'test.not-enabled', @@ -92,8 +97,18 @@ export class FixturePlugin implements Plugin, + res: KibanaResponseFactory + ): Promise> { + const body = req.body; + const text = body && body.text; + + if (text == null) { + return res.badRequest({ body: 'bad request to slack simulator' }); + } + + switch (text) { + case 'success': + return res.ok({ body: 'ok' }); + + case 'no_text': + return res.badRequest({ body: 'no_text' }); + + case 'invalid_payload': + return res.badRequest({ body: 'invalid_payload' }); + + case 'invalid_token': + return res.forbidden({ body: 'invalid_token' }); + + case 'status_500': + return res.internalError({ body: 'simulated slack 500 response' }); + + case 'rate_limit': + const response = { + retry_after: 1, + ok: false, + error: 'rate_limited', + }; + + return res.custom({ + body: Buffer.from('ok'), + statusCode: 429, + headers: { + 'retry-after': '1', + }, + }); + } + + return res.badRequest({ body: 'unknown request to slack simulator' }); + } + ); +} diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/webhook_simulation.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/webhook_simulation.ts new file mode 100644 index 0000000000000..59314511479be --- /dev/null +++ b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators/server/webhook_simulation.ts @@ -0,0 +1,83 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import expect from '@kbn/expect'; +import http from 'http'; +import { fromNullable, map, filter, getOrElse } from 'fp-ts/lib/Option'; +import { pipe } from 'fp-ts/lib/pipeable'; +import { constant } from 'fp-ts/lib/function'; + +export async function initPlugin() { + return http.createServer((request, response) => { + const credentials = pipe( + fromNullable(request.headers.authorization), + map((authorization) => authorization.split(/\s+/)), + filter((parts) => parts.length > 1), + map((parts) => Buffer.from(parts[1], 'base64').toString()), + filter((credentialsPart) => credentialsPart.indexOf(':') !== -1), + map((credentialsPart) => { + const [username, password] = credentialsPart.split(':'); + return { username, password }; + }), + getOrElse(constant({ username: '', password: '' })) + ); + + if (request.method === 'POST' || 'PUT') { + const data: unknown[] = []; + request.on('data', (chunk) => { + data.push(chunk); + }); + request.on('end', () => { + const body = JSON.parse(data.toString()); + switch (body) { + case 'success': + response.statusCode = 200; + response.end('OK'); + return; + case 'authenticate': + return validateAuthentication(credentials, response); + case 'success_post_method': + return validateRequestUsesMethod(request.method ?? '', 'post', response); + case 'success_put_method': + return validateRequestUsesMethod(request.method ?? '', 'put', response); + case 'failure': + response.statusCode = 500; + response.end('Error'); + return; + } + response.statusCode = 400; + response.end( + `unknown request to webhook simulator [${body ? `content: ${body}` : `no content`}]` + ); + return; + }); + } + }); +} + +function validateAuthentication(credentials: any, res: any) { + try { + expect(credentials).to.eql({ + username: 'elastic', + password: 'changeme', + }); + res.statusCode = 200; + res.end('OK'); + } catch (ex) { + res.statusCode = 403; + res.end(`the validateAuthentication operation failed. ${ex.message}`); + } +} + +function validateRequestUsesMethod(requestMethod: string, method: string, res: any) { + try { + expect(requestMethod).to.eql(method); + res.statusCode = 200; + res.end('OK'); + } catch (ex) { + res.statusCode = 403; + res.end(`the validateAuthentication operation failed. ${ex.message}`); + } +} diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/index.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/index.ts deleted file mode 100644 index 43e6a73673556..0000000000000 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import Hapi from 'hapi'; -import { - getExternalServiceSimulatorPath, - NAME, - ExternalServiceSimulator, -} from '../actions_simulators/server/plugin'; - -import { initPlugin as initWebhook } from './webhook_simulation'; -import { initPlugin as initSlack } from './slack_simulation'; - -// eslint-disable-next-line import/no-default-export -export default function (kibana: any) { - return new kibana.Plugin({ - require: ['xpack_main'], - name: `${NAME}-legacy`, - init: (server: Hapi.Server) => { - initWebhook(server, getExternalServiceSimulatorPath(ExternalServiceSimulator.WEBHOOK)); - initSlack(server, getExternalServiceSimulatorPath(ExternalServiceSimulator.SLACK)); - }, - }); -} diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/package.json b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/package.json deleted file mode 100644 index 644cd77d3be75..0000000000000 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "actions-fixtures-legacy", - "version": "0.0.0", - "kibana": { - "version": "kibana" - } -} diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/slack_simulation.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/slack_simulation.ts deleted file mode 100644 index b914386b136cc..0000000000000 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/slack_simulation.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -import Joi from 'joi'; -import Hapi from 'hapi'; - -interface SlackRequest extends Hapi.Request { - payload: { - text: string; - }; -} -export function initPlugin(server: Hapi.Server, path: string) { - server.route({ - method: 'POST', - path, - options: { - auth: false, - validate: { - options: { abortEarly: false }, - payload: Joi.object().keys({ - text: Joi.string(), - }), - }, - }, - handler: slackHandler as Hapi.Lifecycle.Method, - }); -} -// Slack simulator: create a slack action pointing here, and you can get -// different responses based on the message posted. See the README.md for -// more info. - -function slackHandler(request: SlackRequest, h: any) { - const body = request.payload; - const text = body && body.text; - - if (text == null) { - return htmlResponse(h, 400, 'bad request to slack simulator'); - } - - switch (text) { - case 'success': - return htmlResponse(h, 200, 'ok'); - - case 'no_text': - return htmlResponse(h, 400, 'no_text'); - - case 'invalid_payload': - return htmlResponse(h, 400, 'invalid_payload'); - - case 'invalid_token': - return htmlResponse(h, 403, 'invalid_token'); - - case 'status_500': - return htmlResponse(h, 500, 'simulated slack 500 response'); - - case 'rate_limit': - const response = { - retry_after: 1, - ok: false, - error: 'rate_limited', - }; - - return h.response(response).type('application/json').header('retry-after', '1').code(429); - } - - return htmlResponse(h, 400, 'unknown request to slack simulator'); -} - -function htmlResponse(h: any, code: number, text: string) { - return h.response(text).type('text/html').code(code); -} diff --git a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/webhook_simulation.ts b/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/webhook_simulation.ts deleted file mode 100644 index 44e1aff162c92..0000000000000 --- a/x-pack/test/alerting_api_integration/common/fixtures/plugins/actions_simulators_legacy/webhook_simulation.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -import expect from '@kbn/expect'; -import Joi from 'joi'; -import Hapi, { Util } from 'hapi'; -import { fromNullable, map, filter, getOrElse } from 'fp-ts/lib/Option'; -import { pipe } from 'fp-ts/lib/pipeable'; -import { constant } from 'fp-ts/lib/function'; - -interface WebhookRequest extends Hapi.Request { - payload: string; -} - -export async function initPlugin(server: Hapi.Server, path: string) { - server.auth.scheme('identifyCredentialsIfPresent', function identifyCredentialsIfPresent( - s: Hapi.Server, - options?: Hapi.ServerAuthSchemeOptions - ) { - const scheme = { - async authenticate(request: Hapi.Request, h: Hapi.ResponseToolkit) { - const credentials = pipe( - fromNullable(request.headers.authorization), - map((authorization) => authorization.split(/\s+/)), - filter((parts) => parts.length > 1), - map((parts) => Buffer.from(parts[1], 'base64').toString()), - filter((credentialsPart) => credentialsPart.indexOf(':') !== -1), - map((credentialsPart) => { - const [username, password] = credentialsPart.split(':'); - return { username, password }; - }), - getOrElse(constant({ username: '', password: '' })) - ); - - return h.authenticated({ credentials }); - }, - }; - - return scheme; - }); - server.auth.strategy('simple', 'identifyCredentialsIfPresent'); - - server.route({ - method: ['POST', 'PUT'], - path, - options: { - auth: 'simple', - validate: { - options: { abortEarly: false }, - payload: Joi.string(), - }, - }, - handler: webhookHandler as Hapi.Lifecycle.Method, - }); -} - -function webhookHandler(request: WebhookRequest, h: any) { - const body = request.payload; - - switch (body) { - case 'success': - return htmlResponse(h, 200, `OK`); - case 'authenticate': - return validateAuthentication(request, h); - case 'success_post_method': - return validateRequestUsesMethod(request, h, 'post'); - case 'success_put_method': - return validateRequestUsesMethod(request, h, 'put'); - case 'failure': - return htmlResponse(h, 500, `Error`); - } - - return htmlResponse( - h, - 400, - `unknown request to webhook simulator [${body ? `content: ${body}` : `no content`}]` - ); -} - -function validateAuthentication(request: WebhookRequest, h: any) { - const { - auth: { credentials }, - } = request; - try { - expect(credentials).to.eql({ - username: 'elastic', - password: 'changeme', - }); - return htmlResponse(h, 200, `OK`); - } catch (ex) { - return htmlResponse(h, 403, `the validateAuthentication operation failed. ${ex.message}`); - } -} - -function validateRequestUsesMethod( - request: WebhookRequest, - h: any, - method: Util.HTTP_METHODS_PARTIAL -) { - try { - expect(request.method).to.eql(method); - return htmlResponse(h, 200, `OK`); - } catch (ex) { - return htmlResponse(h, 403, `the validateAuthentication operation failed. ${ex.message}`); - } -} - -function htmlResponse(h: any, code: number, text: string) { - return h.response(text).type('text/html').code(code); -} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts index 7eba753d7e98b..b5eb8ec7b303c 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/actions/builtin_action_types/webhook.ts @@ -65,9 +65,7 @@ export default function webhookTest({ getService }: FtrProviderContext) { // need to wait for kibanaServer to settle ... before(() => { - webhookSimulatorURL = kibanaServer.resolveUrl( - getExternalServiceSimulatorPath(ExternalServiceSimulator.WEBHOOK) - ); + webhookSimulatorURL = 'http://localhost:8080'; }); it('should return 200 when creating a webhook action successfully', async () => {