diff --git a/x-pack/plugins/beats/server/routes/api/index.js b/x-pack/plugins/beats/server/routes/api/index.js index 3b0c96834aa3a..4e6ee318668bf 100644 --- a/x-pack/plugins/beats/server/routes/api/index.js +++ b/x-pack/plugins/beats/server/routes/api/index.js @@ -9,7 +9,6 @@ import { registerEnrollBeatRoute } from './register_enroll_beat_route'; import { registerListBeatsRoute } from './register_list_beats_route'; import { registerVerifyBeatsRoute } from './register_verify_beats_route'; import { registerUpdateBeatRoute } from './register_update_beat_route'; -import { registerCreateConfigurationBlockRoute } from './register_create_configuration_block_route'; export function registerApiRoutes(server) { registerCreateEnrollmentTokensRoute(server); @@ -17,5 +16,4 @@ export function registerApiRoutes(server) { registerListBeatsRoute(server); registerVerifyBeatsRoute(server); registerUpdateBeatRoute(server); - registerCreateConfigurationBlockRoute(server); } diff --git a/x-pack/plugins/beats/server/routes/api/register_create_configuration_block_route.js b/x-pack/plugins/beats/server/routes/api/register_create_configuration_block_route.js deleted file mode 100644 index d259b705cf747..0000000000000 --- a/x-pack/plugins/beats/server/routes/api/register_create_configuration_block_route.js +++ /dev/null @@ -1,105 +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 uuid from 'uuid'; -import { get } from 'lodash'; -import { - INDEX_NAMES, - CONFIGURATION_BLOCKS -} from '../../../common/constants'; -import { callWithRequestFactory } from '../../lib/client'; -import { wrapEsError } from '../../lib/error_wrappers'; - -async function getConfigurationBlocksForTag(callWithRequest, tag) { - const params = { - index: INDEX_NAMES.BEATS, - type: '_doc', - q: `type:configuration_block AND configuration_block.tag:${tag}`, - size: 10000, - ignore: [ 404 ] - }; - - const response = await callWithRequest('search', params); - return get(response, 'hits.hits', []).map(hit => hit._source.configuration_block); -} - -function validateUniquenessEnforcingTypes(configurationBlocks, configurationBlockBeingValidated) { - const { type, tag } = configurationBlockBeingValidated; - // If the configuration block being validated is not of a uniqueness-enforcing type, then - // we don't need to perform any further validation checks. - if (!CONFIGURATION_BLOCKS.UNIQUENESS_ENFORCING_TYPES.includes(type)) { - return { isValid: true }; - } - - const isValid = !configurationBlocks.map(block => block.type).includes(type); - return { - isValid, - message: isValid - ? null - : `Configuration block for tag = ${tag} and type = ${type} already exists` - }; -} - -async function validateConfigurationBlock(callWithRequest, configurationBlockBeingValidated) { - const configurationBlocks = await getConfigurationBlocksForTag(callWithRequest, configurationBlockBeingValidated.tag); - return validateUniquenessEnforcingTypes(configurationBlocks, configurationBlockBeingValidated); -} - -function persistConfigurationBlock(callWithRequest, configurationBlock, configurationBlockId) { - const body = { - type: 'configuration_block', - configuration_block: configurationBlock - }; - - const params = { - index: INDEX_NAMES.BEATS, - type: '_doc', - id: `configuration_block:${configurationBlockId}`, - body, - refresh: 'wait_for' - }; - - return callWithRequest('create', params); -} - -// TODO: add license check pre-hook -// TODO: write to Kibana audit log file -export function registerCreateConfigurationBlockRoute(server) { - server.route({ - method: 'POST', - path: '/api/beats/configuration_blocks', - config: { - validate: { - payload: Joi.object({ - type: Joi.string().required().valid(Object.values(CONFIGURATION_BLOCKS.TYPES)), - tag: Joi.string().required(), - block_yml: Joi.string().required() - }).required() - } - }, - handler: async (request, reply) => { - const callWithRequest = callWithRequestFactory(server, request); - - let configurationBlockId; - try { - const configurationBlock = request.payload; - const { isValid, message } = await validateConfigurationBlock(callWithRequest, configurationBlock); - if (!isValid) { - return reply({ message }).code(400); - } - - configurationBlockId = uuid.v4(); - await persistConfigurationBlock(callWithRequest, request.payload, configurationBlockId); - } catch (err) { - return reply(wrapEsError(err)); - } - - const response = { id: configurationBlockId }; - reply(response).code(201); - } - }); -} diff --git a/x-pack/test/api_integration/apis/beats/create_configuration_block.js b/x-pack/test/api_integration/apis/beats/create_configuration_block.js deleted file mode 100644 index 680ff8b2a6d21..0000000000000 --- a/x-pack/test/api_integration/apis/beats/create_configuration_block.js +++ /dev/null @@ -1,149 +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 'expect.js'; -import { - ES_INDEX_NAME, - ES_TYPE_NAME -} from './constants'; - -export default function ({ getService }) { - const supertest = getService('supertest'); - const es = getService('es'); - const chance = getService('chance'); - - describe('create_configuration_block', () => { - it('should create the given configuration block', async () => { - const configurationBlock = { - type: 'output', - tag: 'production', - block_yml: 'elasticsearch:\n hosts: [\"localhost:9200\"]\n username: "..."' - }; - const { body: apiResponse } = await supertest - .post( - '/api/beats/configuration_blocks' - ) - .set('kbn-xsrf', 'xxx') - .send(configurationBlock) - .expect(201); - - const idFromApi = apiResponse.id; - - const esResponse = await es.get({ - index: ES_INDEX_NAME, - type: ES_TYPE_NAME, - id: `configuration_block:${idFromApi}` - }); - - const docInEs = esResponse._source; - - expect(docInEs.type).to.eql('configuration_block'); - expect(docInEs.configuration_block.type).to.eql(configurationBlock.type); - expect(docInEs.configuration_block.tag).to.eql(configurationBlock.tag); - expect(docInEs.configuration_block.block_yml).to.eql(configurationBlock.block_yml); - }); - - it('should not allow two "output" type configuration blocks with the same tag', async () => { - const firstConfigurationBlock = { - type: 'output', - tag: 'production', - block_yml: 'elasticsearch:\n hosts: ["localhost:9200"]\n username: "..."' - }; - await supertest - .post( - '/api/beats/configuration_blocks' - ) - .set('kbn-xsrf', 'xxx') - .send(firstConfigurationBlock) - .expect(201); - - const secondConfigurationBlock = { - type: 'output', - tag: 'production', - block_yml: 'logstash:\n hosts: ["localhost:9000"]\n' - }; - await supertest - .post( - '/api/beats/configuration_blocks' - ) - .set('kbn-xsrf', 'xxx') - .send(secondConfigurationBlock) - .expect(400); - }); - - it('should allow two "output" type configuration blocks with different tags', async () => { - const firstConfigurationBlock = { - type: 'output', - tag: 'production', - block_yml: 'elasticsearch:\n hosts: ["localhost:9200"]\n username: "..."' - }; - await supertest - .post( - '/api/beats/configuration_blocks' - ) - .set('kbn-xsrf', 'xxx') - .send(firstConfigurationBlock) - .expect(201); - - const secondConfigurationBlock = { - type: 'output', - tag: 'development', - block_yml: 'logstash:\n hosts: ["localhost:9000"]\n' - }; - await supertest - .post( - '/api/beats/configuration_blocks' - ) - .set('kbn-xsrf', 'xxx') - .send(secondConfigurationBlock) - .expect(201); - }); - - it('should allow two configuration blocks of different types with the same tag', async () => { - const firstConfigurationBlock = { - type: 'output', - tag: 'production', - block_yml: 'elasticsearch:\n hosts: ["localhost:9200"]\n username: "..."' - }; - await supertest - .post( - '/api/beats/configuration_blocks' - ) - .set('kbn-xsrf', 'xxx') - .send(firstConfigurationBlock) - .expect(201); - - const secondConfigurationBlock = { - type: 'filebeat.inputs', - tag: 'production', - block_yml: 'file:\n path: "/var/log/some.log"]\n' - }; - await supertest - .post( - '/api/beats/configuration_blocks' - ) - .set('kbn-xsrf', 'xxx') - .send(secondConfigurationBlock) - .expect(201); - }); - - - it('should reject a configuration block with an invalid type', async () => { - const firstConfigurationBlock = { - type: chance.word(), - tag: 'production', - block_yml: 'elasticsearch:\n hosts: ["localhost:9200"]\n username: "..."' - }; - await supertest - .post( - '/api/beats/configuration_blocks' - ) - .set('kbn-xsrf', 'xxx') - .send(firstConfigurationBlock) - .expect(400); - }); - }); -} diff --git a/x-pack/test/api_integration/apis/beats/index.js b/x-pack/test/api_integration/apis/beats/index.js index da94353aafeee..b41f17ed749b3 100644 --- a/x-pack/test/api_integration/apis/beats/index.js +++ b/x-pack/test/api_integration/apis/beats/index.js @@ -22,6 +22,5 @@ export default function ({ getService, loadTestFile }) { loadTestFile(require.resolve('./list_beats')); loadTestFile(require.resolve('./verify_beats')); loadTestFile(require.resolve('./update_beat')); - loadTestFile(require.resolve('./create_configuration_block')); }); }