diff --git a/x-pack/plugins/beats_management/public/lib/adapters/beats/adapter_types.ts b/x-pack/plugins/beats_management/public/lib/adapters/beats/adapter_types.ts index 444ae817088e7..b703edb971299 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/beats/adapter_types.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/beats/adapter_types.ts @@ -9,9 +9,8 @@ import { CMBeat } from '../../../../common/domain_types'; export interface CMBeatsAdapter { get(id: string): Promise; getAll(): Promise; - getWithIds(beatIds: string[]): Promise; - removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise; - assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise; + removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise; + assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise; } export interface BeatsTagAssignment { diff --git a/x-pack/plugins/beats_management/public/lib/adapters/beats/memory_beats_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/beats/memory_beats_adapter.ts index e1929a7d6c69a..1940ec2ada4b0 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/beats/memory_beats_adapter.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/beats/memory_beats_adapter.ts @@ -7,7 +7,12 @@ import { omit } from 'lodash'; import { CMBeat } from '../../../../common/domain_types'; -import { BeatsTagAssignment, CMBeatsAdapter } from './adapter_types'; +import { + BeatsRemovalReturn, + BeatsTagAssignment, + CMAssignmentReturn, + CMBeatsAdapter, +} from './adapter_types'; export class MemoryBeatsAdapter implements CMBeatsAdapter { private beatsDB: CMBeat[]; @@ -20,15 +25,11 @@ export class MemoryBeatsAdapter implements CMBeatsAdapter { return this.beatsDB.find(beat => beat.id === id) || null; } - public async getWithIds(beatIds: string[]) { - return this.beatsDB.filter(beat => beatIds.includes(beat.id)); - } - public async getAll() { return this.beatsDB.map((beat: any) => omit(beat, ['access_token'])); } - public async removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise { + public async removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise { const beatIds = removals.map(r => r.beatId); const response = this.beatsDB.filter(beat => beatIds.includes(beat.id)).map(beat => { @@ -48,7 +49,7 @@ export class MemoryBeatsAdapter implements CMBeatsAdapter { })); } - public async assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise { + public async assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise { const beatIds = assignments.map(r => r.beatId); this.beatsDB.filter(beat => beatIds.includes(beat.id)).map(beat => { diff --git a/x-pack/plugins/beats_management/public/lib/adapters/beats/rest_beats_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/beats/rest_beats_adapter.ts new file mode 100644 index 0000000000000..9da760be307db --- /dev/null +++ b/x-pack/plugins/beats_management/public/lib/adapters/beats/rest_beats_adapter.ts @@ -0,0 +1,37 @@ +/* + * 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 { CMBeat } from '../../../../common/domain_types'; +import { RestAPIAdapter } from '../rest_api/adapter_types'; +import { + BeatsRemovalReturn, + BeatsTagAssignment, + CMAssignmentReturn, + CMBeatsAdapter, +} from './adapter_types'; +export class RestBeatsAdapter implements CMBeatsAdapter { + constructor(private readonly REST: RestAPIAdapter) {} + + public async get(id: string): Promise { + return await this.REST.get(`/api/beats/agent/${id}`); + } + + public async getAll(): Promise { + return await this.REST.get('/api/beats/agents'); + } + + public async removeTagsFromBeats(removals: BeatsTagAssignment[]): Promise { + return await this.REST.post(`/api/beats/agents_tags/removals`, { + removals, + }); + } + + public async assignTagsToBeats(assignments: BeatsTagAssignment[]): Promise { + return await this.REST.post(`/api/beats/agents_tags/assignments`, { + assignments, + }); + } +} diff --git a/x-pack/plugins/beats_management/public/lib/adapters/rest_api/adapter_types.ts b/x-pack/plugins/beats_management/public/lib/adapters/rest_api/adapter_types.ts new file mode 100644 index 0000000000000..222807e7f6948 --- /dev/null +++ b/x-pack/plugins/beats_management/public/lib/adapters/rest_api/adapter_types.ts @@ -0,0 +1,12 @@ +/* + * 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. + */ + +export interface RestAPIAdapter { + get(url: string): Promise; + post(url: string, body?: { [key: string]: any }): Promise; + delete(url: string): Promise; + put(url: string, body?: any): Promise; +} diff --git a/x-pack/plugins/beats_management/public/lib/adapters/rest_api/axios_rest_api_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/rest_api/axios_rest_api_adapter.ts new file mode 100644 index 0000000000000..b05f2b41e30b3 --- /dev/null +++ b/x-pack/plugins/beats_management/public/lib/adapters/rest_api/axios_rest_api_adapter.ts @@ -0,0 +1,81 @@ +/* + * 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 axios, { AxiosInstance } from 'axios'; +import { RestAPIAdapter } from './adapter_types'; +let globalAPI: AxiosInstance; + +export class AxiosRestAPIAdapter implements RestAPIAdapter { + constructor( + private readonly kbnVersion: string, + private readonly xsrfToken: string, + private readonly basePath: string + ) {} + + public async get(url: string): Promise { + return await this.REST.get(url).then(resp => resp.data); + } + + public async post( + url: string, + body?: { [key: string]: any } + ): Promise { + return await this.REST.post(url, body).then(resp => resp.data); + } + + public async delete(url: string): Promise { + return await this.REST.delete(url).then(resp => resp.data); + } + + public async put(url: string, body?: any): Promise { + return await this.REST.put(url, body).then(resp => resp.data); + } + + private get REST() { + if (globalAPI) { + return globalAPI; + } + + globalAPI = axios.create({ + baseURL: this.basePath, + withCredentials: true, + responseType: 'json', + timeout: 30000, + headers: { + Accept: 'application/json', + credentials: 'same-origin', + 'Content-Type': 'application/json', + 'kbn-version': this.kbnVersion, + 'kbn-xsrf': this.xsrfToken, + }, + }); + // Add a request interceptor + globalAPI.interceptors.request.use( + config => { + // Do something before request is sent + return config; + }, + error => { + // Do something with request error + return Promise.reject(error); + } + ); + + // Add a response interceptor + globalAPI.interceptors.response.use( + response => { + // Do something with response data + return response; + }, + error => { + // Do something with response error + return Promise.reject(error); + } + ); + + return globalAPI; + } +} diff --git a/x-pack/plugins/beats_management/public/lib/adapters/tags/adapter_types.ts b/x-pack/plugins/beats_management/public/lib/adapters/tags/adapter_types.ts index ab0931ab597bf..57bdf2592baa3 100644 --- a/x-pack/plugins/beats_management/public/lib/adapters/tags/adapter_types.ts +++ b/x-pack/plugins/beats_management/public/lib/adapters/tags/adapter_types.ts @@ -8,5 +8,5 @@ import { BeatTag } from '../../../../common/domain_types'; export interface CMTagsAdapter { getTagsWithIds(tagIds: string[]): Promise; getAll(): Promise; - upsertTag(tag: BeatTag): Promise<{}>; + upsertTag(tag: BeatTag): Promise; } diff --git a/x-pack/plugins/beats_management/public/lib/adapters/tags/rest_tags_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/tags/rest_tags_adapter.ts new file mode 100644 index 0000000000000..5eb16762ba825 --- /dev/null +++ b/x-pack/plugins/beats_management/public/lib/adapters/tags/rest_tags_adapter.ts @@ -0,0 +1,27 @@ +/* + * 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 { BeatTag } from '../../../../common/domain_types'; +import { RestAPIAdapter } from '../rest_api/adapter_types'; +import { CMTagsAdapter } from './adapter_types'; + +export class RestTagsAdapter implements CMTagsAdapter { + constructor(private readonly REST: RestAPIAdapter) {} + + public async getTagsWithIds(tagIds: string[]): Promise { + return await this.REST.get(`/api/beats/tags/${tagIds.join(',')}`); + } + + public async getAll(): Promise { + return await this.REST.get(`/api/beats/tags`); + } + + public async upsertTag(tag: BeatTag): Promise { + return await this.REST.put(`/api/beats/tag/{tag}`, { + configuration_blocks: tag.configuration_blocks, + }); + } +} diff --git a/x-pack/plugins/beats_management/public/lib/adapters/tokens/rest_tokens_adapter.ts b/x-pack/plugins/beats_management/public/lib/adapters/tokens/rest_tokens_adapter.ts new file mode 100644 index 0000000000000..de5890fdaebf5 --- /dev/null +++ b/x-pack/plugins/beats_management/public/lib/adapters/tokens/rest_tokens_adapter.ts @@ -0,0 +1,17 @@ +/* + * 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 { RestAPIAdapter } from '../rest_api/adapter_types'; +import { CMTokensAdapter, TokenEnrollmentData } from './adapter_types'; + +export class RestTokensAdapter implements CMTokensAdapter { + constructor(private readonly REST: RestAPIAdapter) {} + + public async createEnrollmentToken(): Promise { + const tokens = await this.REST.post('/api/beats/enrollment_tokens'); + return tokens[0]; + } +} diff --git a/x-pack/plugins/beats_management/public/lib/compose/kibana.ts b/x-pack/plugins/beats_management/public/lib/compose/kibana.ts index f27f553c9f327..9f8f183170fd1 100644 --- a/x-pack/plugins/beats_management/public/lib/compose/kibana.ts +++ b/x-pack/plugins/beats_management/public/lib/compose/kibana.ts @@ -6,23 +6,28 @@ import 'ui/autoload/all'; // @ts-ignore: path dynamic for kibana +import chrome from 'ui/chrome'; +// @ts-ignore: path dynamic for kibana import { management } from 'ui/management'; // @ts-ignore: path dynamic for kibana import { uiModules } from 'ui/modules'; // @ts-ignore: path dynamic for kibana import routes from 'ui/routes'; // @ts-ignore: path dynamic for kibana -import { MemoryBeatsAdapter } from '../adapters/beats/memory_beats_adapter'; +import { RestBeatsAdapter } from '../adapters/beats/rest_beats_adapter'; import { KibanaFrameworkAdapter } from '../adapters/framework/kibana_framework_adapter'; -import { MemoryTagsAdapter } from '../adapters/tags/memory_tags_adapter'; -import { MemoryTokensAdapter } from '../adapters/tokens/memory_tokens_adapter'; +import { AxiosRestAPIAdapter } from '../adapters/rest_api/axios_rest_api_adapter'; +import { RestTagsAdapter } from '../adapters/tags/rest_tags_adapter'; +import { RestTokensAdapter } from '../adapters/tokens/rest_tokens_adapter'; import { FrontendDomainLibs, FrontendLibs } from '../lib'; export function compose(): FrontendLibs { - // const kbnVersion = (window as any).__KBN__.version; - const tags = new MemoryTagsAdapter([]); - const tokens = new MemoryTokensAdapter(); - const beats = new MemoryBeatsAdapter([]); + const kbnVersion = (window as any).__KBN__.version; + const api = new AxiosRestAPIAdapter(kbnVersion, chrome.getXsrfToken(), chrome.getBasePath()); + + const tags = new RestTagsAdapter(api); + const tokens = new RestTokensAdapter(api); + const beats = new RestBeatsAdapter(api); const domainLibs: FrontendDomainLibs = { tags, diff --git a/x-pack/plugins/beats_management/server/lib/adapters/beats/adapter_types.ts b/x-pack/plugins/beats_management/server/lib/adapters/beats/adapter_types.ts index 8812d9d39bd41..0d68fd528d42a 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/beats/adapter_types.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/beats/adapter_types.ts @@ -11,7 +11,7 @@ import { FrameworkUser } from '../framework/adapter_types'; export interface CMBeatsAdapter { insert(beat: CMBeat): Promise; update(beat: CMBeat): Promise; - get(id: string): any; + get(user: FrameworkUser, id: string): any; getAll(user: FrameworkUser): any; getWithIds(user: FrameworkUser, beatIds: string[]): any; removeTagsFromBeats( diff --git a/x-pack/plugins/beats_management/server/lib/adapters/beats/elasticsearch_beats_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/beats/elasticsearch_beats_adapter.ts index 9a3d067ffa35f..1d00f95e3a4e0 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/beats/elasticsearch_beats_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/beats/elasticsearch_beats_adapter.ts @@ -21,7 +21,7 @@ export class ElasticsearchBeatsAdapter implements CMBeatsAdapter { this.framework = framework; } - public async get(id: string) { + public async get(user: FrameworkUser, id: string) { const params = { id: `beat:${id}`, ignore: [404], @@ -29,7 +29,7 @@ export class ElasticsearchBeatsAdapter implements CMBeatsAdapter { type: '_doc', }; - const response = await this.database.get(this.framework.internalUser, params); + const response = await this.database.get(user, params); if (!response.found) { return null; } diff --git a/x-pack/plugins/beats_management/server/lib/adapters/beats/memory_beats_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/beats/memory_beats_adapter.ts index 1762ff93fc185..1de1fe71e54ea 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/beats/memory_beats_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/beats/memory_beats_adapter.ts @@ -17,7 +17,7 @@ export class MemoryBeatsAdapter implements CMBeatsAdapter { this.beatsDB = beatsDB; } - public async get(id: string) { + public async get(user: FrameworkUser, id: string) { return this.beatsDB.find(beat => beat.id === id) || null; } diff --git a/x-pack/plugins/beats_management/server/lib/adapters/framework/testing_framework_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/framework/testing_framework_adapter.ts index 3280220893892..5462bd36b48ae 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/framework/testing_framework_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/framework/testing_framework_adapter.ts @@ -3,13 +3,11 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ -import { Client } from 'elasticsearch'; -import { get } from 'lodash'; + import { FrameworkInternalUser } from './adapter_types'; import { BackendFrameworkAdapter, - FrameworkRequest, FrameworkRouteOptions, FrameworkWrappableRequest, } from './adapter_types'; @@ -24,15 +22,15 @@ export class TestingBackendFrameworkAdapter implements BackendFrameworkAdapter { kind: 'internal', }; public version: string; - private client: Client | null; private settings: TestSettings; - constructor(client: Client | null, settings: TestSettings) { - this.client = client; - this.settings = settings || { + constructor( + settings: TestSettings = { encryptionKey: 'something_who_cares', enrollmentTokensTtlInSeconds: 10 * 60, // 10 minutes - }; + } + ) { + this.settings = settings; this.version = 'testing'; } @@ -54,24 +52,4 @@ export class TestingBackendFrameworkAdapter implements BackendFrameworkAdapter { ) { // not yet testable } - - public installIndexTemplate(name: string, template: {}) { - return; - } - - public async callWithInternalUser(esMethod: string, options: {}) { - const api = get(this.client, esMethod); - - api(options); - - return await api(options); - } - - public async callWithRequest(req: FrameworkRequest, esMethod: string, options: {}) { - const api = get(this.client, esMethod); - - api(options); - - return await api(options); - } } diff --git a/x-pack/plugins/beats_management/server/lib/adapters/tags/adapter_types.ts b/x-pack/plugins/beats_management/server/lib/adapters/tags/adapter_types.ts index 7bbb42d415f52..77ae4ff8ad095 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/tags/adapter_types.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/tags/adapter_types.ts @@ -7,6 +7,7 @@ import { BeatTag } from '../../../../common/domain_types'; import { FrameworkUser } from '../framework/adapter_types'; export interface CMTagsAdapter { + getAll(user: FrameworkUser): Promise; getTagsWithIds(user: FrameworkUser, tagIds: string[]): Promise; upsertTag(user: FrameworkUser, tag: BeatTag): Promise<{}>; } diff --git a/x-pack/plugins/beats_management/server/lib/adapters/tags/elasticsearch_tags_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/tags/elasticsearch_tags_adapter.ts index 2c2c988189283..645ed37f5ff8f 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/tags/elasticsearch_tags_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/tags/elasticsearch_tags_adapter.ts @@ -19,6 +19,17 @@ export class ElasticsearchTagsAdapter implements CMTagsAdapter { this.database = database; } + public async getAll(user: FrameworkUser) { + const params = { + index: INDEX_NAMES.BEATS, + q: 'type:tag', + type: '_doc', + }; + const response = await this.database.search(user, params); + + return get(response, 'hits.hits', []); + } + public async getTagsWithIds(user: FrameworkUser, tagIds: string[]) { const ids = tagIds.map(tag => `tag:${tag}`); diff --git a/x-pack/plugins/beats_management/server/lib/adapters/tags/memory_tags_adapter.ts b/x-pack/plugins/beats_management/server/lib/adapters/tags/memory_tags_adapter.ts index c3470011f6a4e..7623c8aaa21d8 100644 --- a/x-pack/plugins/beats_management/server/lib/adapters/tags/memory_tags_adapter.ts +++ b/x-pack/plugins/beats_management/server/lib/adapters/tags/memory_tags_adapter.ts @@ -15,6 +15,10 @@ export class MemoryTagsAdapter implements CMTagsAdapter { this.tagsDB = tagsDB; } + public async getAll(user: FrameworkUser) { + return this.tagsDB; + } + public async getTagsWithIds(user: FrameworkUser, tagIds: string[]) { return this.tagsDB.filter(tag => tagIds.includes(tag.id)); } diff --git a/x-pack/plugins/beats_management/server/lib/compose/testing.ts b/x-pack/plugins/beats_management/server/lib/compose/testing.ts new file mode 100644 index 0000000000000..25b6776b6908b --- /dev/null +++ b/x-pack/plugins/beats_management/server/lib/compose/testing.ts @@ -0,0 +1,53 @@ +/* + * 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 { MemoryBeatsAdapter } from '../adapters/beats/memory_beats_adapter'; +import { MemoryTagsAdapter } from '../adapters/tags/memory_tags_adapter'; +import { MemoryTokensAdapter } from '../adapters/tokens/memory_tokens_adapter'; + +import { TestingBackendFrameworkAdapter } from '../adapters/framework/testing_framework_adapter'; + +import { CMBeatsDomain } from '../domains/beats'; +import { CMTagsDomain } from '../domains/tags'; +import { CMTokensDomain } from '../domains/tokens'; + +import { BeatTag, CMBeat } from '../../../common/domain_types'; +import { TokenEnrollmentData } from '../adapters/tokens/adapter_types'; +import { CMDomainLibs, CMServerLibs } from '../lib'; + +export function compose({ + tagsDB = [], + tokensDB = [], + beatsDB = [], +}: { + tagsDB?: BeatTag[]; + tokensDB?: TokenEnrollmentData[]; + beatsDB?: CMBeat[]; +}): CMServerLibs { + const framework = new TestingBackendFrameworkAdapter(); + + const tags = new CMTagsDomain(new MemoryTagsAdapter(tagsDB)); + const tokens = new CMTokensDomain(new MemoryTokensAdapter(tokensDB), { + framework, + }); + const beats = new CMBeatsDomain(new MemoryBeatsAdapter(beatsDB), { + tags, + tokens, + }); + + const domainLibs: CMDomainLibs = { + beats, + tags, + tokens, + }; + + const libs: CMServerLibs = { + framework, + ...domainLibs, + }; + + return libs; +} diff --git a/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/assign_tags.test.ts b/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/assign_tags.test.ts index d0d888d2d3d1f..20f4a7d36e4f0 100644 --- a/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/assign_tags.test.ts +++ b/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/assign_tags.test.ts @@ -82,7 +82,7 @@ describe('Beats Domain Lib', () => { id: 'qa', }, ]; - const framework = new TestingBackendFrameworkAdapter(null, settings); + const framework = new TestingBackendFrameworkAdapter(settings); const tokensLib = new CMTokensDomain(new MemoryTokensAdapter([]), { framework, diff --git a/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/enroll.test.ts b/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/enroll.test.ts index 9f42ad3c89f86..c5bc0935dc6cc 100644 --- a/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/enroll.test.ts +++ b/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/enroll.test.ts @@ -70,7 +70,7 @@ describe('Beats Domain Lib', () => { version, }; - const framework = new TestingBackendFrameworkAdapter(null, settings); + const framework = new TestingBackendFrameworkAdapter(settings); tokensLib = new CMTokensDomain(new MemoryTokensAdapter(tokensDB), { framework, diff --git a/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/remove_tags.test.ts b/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/remove_tags.test.ts new file mode 100644 index 0000000000000..f75334e917c2b --- /dev/null +++ b/x-pack/plugins/beats_management/server/lib/domains/__tests__/beats/remove_tags.test.ts @@ -0,0 +1,100 @@ +/* + * 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 { BeatTag, CMBeat } from '../../../../../common/domain_types'; +import { compose } from '../../../compose/testing'; +import { CMServerLibs } from '../../../lib'; +import { FrameworkInternalUser } from './../../../adapters/framework/adapter_types'; + +const internalUser: FrameworkInternalUser = { kind: 'internal' }; + +describe('Beats Domain Lib', () => { + let libs: CMServerLibs; + let beatsDB: CMBeat[] = []; + let tagsDB: BeatTag[] = []; + + describe('remove_tags_from_beats', () => { + beforeEach(async () => { + beatsDB = [ + { + access_token: '9a6c99ae0fd84b068819701169cd8a4b', + host_ip: '1.2.3.4', + host_name: 'foo.bar.com', + id: 'qux', + type: 'filebeat', + }, + { + access_token: '188255eb560a4448b72656c5e99cae6f', + host_ip: '22.33.11.44', + host_name: 'baz.bar.com', + id: 'baz', + type: 'metricbeat', + }, + { + access_token: '93c4a4dd08564c189a7ec4e4f046b975', + host_ip: '1.2.3.4', + host_name: 'foo.bar.com', + id: 'foo', + tags: ['production', 'qa'], + type: 'metricbeat', + verified_on: '2018-05-15T16:25:38.924Z', + }, + { + access_token: '3c4a4dd08564c189a7ec4e4f046b9759', + host_ip: '11.22.33.44', + host_name: 'foo.com', + id: 'bar', + type: 'filebeat', + }, + ]; + tagsDB = [ + { + configuration_blocks: [], + id: 'production', + }, + { + configuration_blocks: [], + id: 'development', + }, + { + configuration_blocks: [], + id: 'qa', + }, + ]; + + libs = compose({ + tagsDB, + beatsDB, + }); + }); + + it('should remove a single tag from a single beat', async () => { + const apiResponse = await libs.beats.removeTagsFromBeats(internalUser, [ + { beatId: 'foo', tag: 'production' }, + ]); + + expect(apiResponse.removals).toEqual([{ status: 200, result: 'updated' }]); + // @ts-ignore + expect(beatsDB.find(b => b.id === 'foo').tags).toEqual(['qa']); + }); + + it('should remove a single tag from a multiple beats', async () => { + const apiResponse = await libs.beats.removeTagsFromBeats(internalUser, [ + { beatId: 'foo', tag: 'development' }, + { beatId: 'bar', tag: 'development' }, + ]); + + expect(apiResponse.removals).toEqual([ + { status: 200, result: 'updated' }, + { status: 200, result: 'updated' }, + ]); + + // @ts-ignore + expect(beatsDB.find(b => b.id === 'foo').tags).toEqual(['production', 'qa']); + expect(beatsDB.find(b => b.id === 'bar')).not.toHaveProperty('tags'); + }); + }); +}); diff --git a/x-pack/plugins/beats_management/server/lib/domains/__tests__/tokens.test.ts b/x-pack/plugins/beats_management/server/lib/domains/__tests__/tokens.test.ts index c89962dca7d3b..eca217b3c8ed1 100644 --- a/x-pack/plugins/beats_management/server/lib/domains/__tests__/tokens.test.ts +++ b/x-pack/plugins/beats_management/server/lib/domains/__tests__/tokens.test.ts @@ -28,7 +28,7 @@ describe('Token Domain Lib', () => { beforeEach(async () => { tokensDB = []; - framework = new TestingBackendFrameworkAdapter(null, settings); + framework = new TestingBackendFrameworkAdapter(settings); tokensLib = new CMTokensDomain(new MemoryTokensAdapter(tokensDB), { framework, diff --git a/x-pack/plugins/beats_management/server/lib/domains/beats.ts b/x-pack/plugins/beats_management/server/lib/domains/beats.ts index 618de8ab0b446..f3c98b056d5e1 100644 --- a/x-pack/plugins/beats_management/server/lib/domains/beats.ts +++ b/x-pack/plugins/beats_management/server/lib/domains/beats.ts @@ -14,28 +14,33 @@ import { FrameworkUser } from '../adapters/framework/adapter_types'; import { CMAssignmentReturn } from '../adapters/beats/adapter_types'; import { BeatsRemovalReturn } from '../adapters/beats/adapter_types'; -import { BeatEnrollmentStatus, CMDomainLibs } from '../lib'; +import { BeatEnrollmentStatus, CMDomainLibs, CMServerLibs } from '../lib'; export class CMBeatsDomain { - private adapter: CMBeatsAdapter; private tags: CMDomainLibs['tags']; private tokens: CMDomainLibs['tokens']; + private framework: CMServerLibs['framework']; constructor( - adapter: CMBeatsAdapter, - libs: { tags: CMDomainLibs['tags']; tokens: CMDomainLibs['tokens'] } + private readonly adapter: CMBeatsAdapter, + libs: { + tags: CMDomainLibs['tags']; + tokens: CMDomainLibs['tokens']; + framework: CMServerLibs['framework']; + } ) { this.adapter = adapter; this.tags = libs.tags; this.tokens = libs.tokens; + this.framework = libs.framework; } - public async getById(beatId: string) { - return await this.adapter.get(beatId); + public async getById(user: FrameworkUser, beatId: string) { + return await this.adapter.get(user, beatId); } public async update(beatId: string, accessToken: string, beatData: Partial) { - const beat = await this.adapter.get(beatId); + const beat = await this.adapter.get(this.framework.internalUser, beatId); const { verified: isAccessTokenValid } = this.tokens.verifyToken( beat ? beat.access_token : '', @@ -190,6 +195,7 @@ function addNonExistentItemToResponse( ) { assignments.forEach(({ beatId, tag }: BeatsTagAssignment, idx: any) => { const isBeatNonExistent = nonExistentBeatIds.includes(beatId); + const isTagNonExistent = nonExistentTags.includes(tag); if (isBeatNonExistent && isTagNonExistent) { diff --git a/x-pack/plugins/beats_management/server/lib/domains/tags.ts b/x-pack/plugins/beats_management/server/lib/domains/tags.ts index 36cf9a5e6d7f0..39bc2c147ea03 100644 --- a/x-pack/plugins/beats_management/server/lib/domains/tags.ts +++ b/x-pack/plugins/beats_management/server/lib/domains/tags.ts @@ -18,6 +18,10 @@ export class CMTagsDomain { this.adapter = adapter; } + public async getAll(user: FrameworkUser) { + return await this.adapter.getAll(user); + } + public async getTagsWithIds(user: FrameworkUser, tagIds: string[]) { return await this.adapter.getTagsWithIds(user, tagIds); } diff --git a/x-pack/plugins/beats_management/server/lib/lib.ts b/x-pack/plugins/beats_management/server/lib/lib.ts index 495093842b496..824c5722a4bd8 100644 --- a/x-pack/plugins/beats_management/server/lib/lib.ts +++ b/x-pack/plugins/beats_management/server/lib/lib.ts @@ -18,7 +18,7 @@ export interface CMDomainLibs { export interface CMServerLibs extends CMDomainLibs { framework: BackendFrameworkAdapter; - database: DatabaseAdapter; + database?: DatabaseAdapter; } export enum BeatEnrollmentStatus { diff --git a/x-pack/plugins/beats_management/server/management_server.ts b/x-pack/plugins/beats_management/server/management_server.ts index 1c8a1d727175e..f7316ea0887ff 100644 --- a/x-pack/plugins/beats_management/server/management_server.ts +++ b/x-pack/plugins/beats_management/server/management_server.ts @@ -16,10 +16,12 @@ import { createTokensRoute } from './rest_api/tokens/create'; import { beatsIndexTemplate } from './utils/index_templates'; export const initManagementServer = (libs: CMServerLibs) => { - libs.database.putTemplate(libs.framework.internalUser, { - name: 'beats-template', - body: beatsIndexTemplate, - }); + if (libs.database) { + libs.database.putTemplate(libs.framework.internalUser, { + name: 'beats-template', + body: beatsIndexTemplate, + }); + } libs.framework.registerRoute(createGetBeatConfigurationRoute(libs)); libs.framework.registerRoute(createTagAssignmentsRoute(libs)); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts b/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts index 81906ea9473e6..dad9909ddd1e0 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/configuration.ts @@ -27,7 +27,7 @@ export const createGetBeatConfigurationRoute = (libs: CMServerLibs) => ({ let beat; let tags; try { - beat = await libs.beats.getById(beatId); + beat = await libs.beats.getById(libs.framework.internalUser, beatId); if (beat === null) { return reply({ message: 'Beat not found' }).code(404); } diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts index c0f0185fbde25..c1c23537218bd 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/enroll.ts @@ -13,6 +13,8 @@ import { wrapEsError } from '../../utils/error_wrappers'; // TODO: add license check pre-hook // TODO: write to Kibana audit log file export const createBeatEnrollmentRoute = (libs: CMServerLibs) => ({ + method: 'POST', + path: '/api/beats/agent/{beatId}', config: { auth: false, validate: { @@ -58,6 +60,4 @@ export const createBeatEnrollmentRoute = (libs: CMServerLibs) => ({ return reply(wrapEsError(err)); } }, - method: 'POST', - path: '/api/beats/agent/{beatId}', }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/get.ts b/x-pack/plugins/beats_management/server/rest_api/beats/get.ts new file mode 100644 index 0000000000000..e7ed5ef5c2cc8 --- /dev/null +++ b/x-pack/plugins/beats_management/server/rest_api/beats/get.ts @@ -0,0 +1,39 @@ +/* + * 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 { CMBeat } from '../../../common/domain_types'; +import { CMServerLibs } from '../../lib/lib'; +import { wrapEsError } from '../../utils/error_wrappers'; + +export const createGetBeatRoute = (libs: CMServerLibs) => ({ + method: 'GET', + path: '/api/beats/agent/{beatId}', + config: { + validate: { + headers: Joi.object({ + 'kbn-beats-access-token': Joi.string().required(), + }).options({ allowUnknown: true }), + }, + }, + handler: async (request: any, reply: any) => { + const beatId = request.params.beatId; + + let beat: CMBeat; + try { + beat = await libs.beats.getById(request.user, beatId); + if (beat === null) { + return reply({ message: 'Beat not found' }).code(404); + } + } catch (err) { + return reply(wrapEsError(err)); + } + + delete beat.access_token; + + reply(beat); + }, +}); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/list.ts b/x-pack/plugins/beats_management/server/rest_api/beats/list.ts index a47bfcfbf3853..72105fc2f5440 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/list.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/list.ts @@ -10,6 +10,8 @@ import { wrapEsError } from '../../utils/error_wrappers'; // TODO: add license check pre-hook export const createListAgentsRoute = (libs: CMServerLibs) => ({ + method: 'GET', + path: '/api/beats/agents', handler: async (request: FrameworkRequest, reply: any) => { try { const beats = await libs.beats.getAllBeats(request.user); @@ -19,6 +21,4 @@ export const createListAgentsRoute = (libs: CMServerLibs) => ({ return reply(wrapEsError(err)); } }, - method: 'GET', - path: '/api/beats/agents', }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts b/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts index 9c832ee3226b8..857b68a921597 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/tag_assignment.ts @@ -5,19 +5,23 @@ */ import Joi from 'joi'; +import { BeatsTagAssignment } from '../../../public/lib/adapters/beats/adapter_types'; import { FrameworkRequest } from '../../lib/adapters/framework/adapter_types'; + import { CMServerLibs } from '../../lib/lib'; import { wrapEsError } from '../../utils/error_wrappers'; // TODO: add license check pre-hook // TODO: write to Kibana audit log file export const createTagAssignmentsRoute = (libs: CMServerLibs) => ({ + method: 'POST', + path: '/api/beats/agents_tags/assignments', config: { validate: { payload: Joi.object({ assignments: Joi.array().items( Joi.object({ - beat_id: Joi.string().required(), + beatId: Joi.string().required(), tag: Joi.string().required(), }) ), @@ -25,22 +29,14 @@ export const createTagAssignmentsRoute = (libs: CMServerLibs) => ({ }, }, handler: async (request: FrameworkRequest, reply: any) => { - const { assignments } = request.payload; - - // TODO abstract or change API to keep beatId consistent - const tweakedAssignments = assignments.map((assignment: any) => ({ - beatId: assignment.beat_id, - tag: assignment.tag, - })); + const { assignments }: { assignments: BeatsTagAssignment[] } = request.payload; try { - const response = await libs.beats.assignTagsToBeats(request.user, tweakedAssignments); + const response = await libs.beats.assignTagsToBeats(request.user, assignments); reply(response); } catch (err) { // TODO move this to kibana route thing in adapter return reply(wrapEsError(err)); } }, - method: 'POST', - path: '/api/beats/agents_tags/assignments', }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts b/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts index 6a7af3b42d407..eaec8f2872172 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/tag_removal.ts @@ -12,6 +12,8 @@ import { wrapEsError } from '../../utils/error_wrappers'; // TODO: add license check pre-hook // TODO: write to Kibana audit log file export const createTagRemovalsRoute = (libs: CMServerLibs) => ({ + method: 'POST', + path: '/api/beats/agents_tags/removals', config: { validate: { payload: Joi.object({ @@ -41,6 +43,4 @@ export const createTagRemovalsRoute = (libs: CMServerLibs) => ({ return reply(wrapEsError(err)); } }, - method: 'POST', - path: '/api/beats/agents_tags/removals', }); diff --git a/x-pack/plugins/beats_management/server/rest_api/beats/update.ts b/x-pack/plugins/beats_management/server/rest_api/beats/update.ts index 60d7151731cd3..9c8e7daf475f8 100644 --- a/x-pack/plugins/beats_management/server/rest_api/beats/update.ts +++ b/x-pack/plugins/beats_management/server/rest_api/beats/update.ts @@ -12,6 +12,8 @@ import { wrapEsError } from '../../utils/error_wrappers'; // TODO: add license check pre-hook // TODO: write to Kibana audit log file (include who did the verification as well) export const createBeatUpdateRoute = (libs: CMServerLibs) => ({ + method: 'PUT', + path: '/api/beats/agent/{beatId}', config: { auth: false, validate: { @@ -56,6 +58,4 @@ export const createBeatUpdateRoute = (libs: CMServerLibs) => ({ return reply(wrapEsError(err)); } }, - method: 'PUT', - path: '/api/beats/agent/{beatId}', }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/get.ts b/x-pack/plugins/beats_management/server/rest_api/tags/get.ts new file mode 100644 index 0000000000000..97aa6b413aeb3 --- /dev/null +++ b/x-pack/plugins/beats_management/server/rest_api/tags/get.ts @@ -0,0 +1,27 @@ +/* + * 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 { BeatTag } from '../../../common/domain_types'; +import { CMServerLibs } from '../../lib/lib'; +import { wrapEsError } from '../../utils/error_wrappers'; + +export const createGetTagsWithIdsRoute = (libs: CMServerLibs) => ({ + method: 'GET', + path: '/api/beats/tags/{tagIds}', + handler: async (request: any, reply: any) => { + const tagIdString: string = request.params.tagIds; + const tagIds = tagIdString.split(',').filter((id: string) => id.length > 0); + + let tags: BeatTag[]; + try { + tags = await libs.tags.getTagsWithIds(request.user, tagIds); + } catch (err) { + return reply(wrapEsError(err)); + } + + reply(tags); + }, +}); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/list.ts b/x-pack/plugins/beats_management/server/rest_api/tags/list.ts new file mode 100644 index 0000000000000..41874a77eef0f --- /dev/null +++ b/x-pack/plugins/beats_management/server/rest_api/tags/list.ts @@ -0,0 +1,24 @@ +/* + * 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 { BeatTag } from '../../../common/domain_types'; +import { CMServerLibs } from '../../lib/lib'; +import { wrapEsError } from '../../utils/error_wrappers'; + +export const createListTagsRoute = (libs: CMServerLibs) => ({ + method: 'GET', + path: '/api/beats/tags/', + handler: async (request: any, reply: any) => { + let tags: BeatTag[]; + try { + tags = await libs.tags.getAll(request.user); + } catch (err) { + return reply(wrapEsError(err)); + } + + reply(tags); + }, +}); diff --git a/x-pack/plugins/beats_management/server/rest_api/tags/set.ts b/x-pack/plugins/beats_management/server/rest_api/tags/set.ts index 6c01959e75311..f50721e764ef3 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tags/set.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tags/set.ts @@ -14,6 +14,8 @@ import { wrapEsError } from '../../utils/error_wrappers'; // TODO: add license check pre-hook // TODO: write to Kibana audit log file export const createSetTagRoute = (libs: CMServerLibs) => ({ + method: 'PUT', + path: '/api/beats/tag/{tag}', config: { validate: { params: Joi.object({ @@ -49,6 +51,4 @@ export const createSetTagRoute = (libs: CMServerLibs) => ({ return reply(wrapEsError(err)); } }, - method: 'PUT', - path: '/api/beats/tag/{tag}', }); diff --git a/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts b/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts index 74278703347c3..15ab7b872df8a 100644 --- a/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts +++ b/x-pack/plugins/beats_management/server/rest_api/tokens/create.ts @@ -13,6 +13,8 @@ import { wrapEsError } from '../../utils/error_wrappers'; // TODO: write to Kibana audit log file const DEFAULT_NUM_TOKENS = 1; export const createTokensRoute = (libs: CMServerLibs) => ({ + method: 'POST', + path: '/api/beats/enrollment_tokens', config: { validate: { payload: Joi.object({ @@ -34,6 +36,4 @@ export const createTokensRoute = (libs: CMServerLibs) => ({ return reply(wrapEsError(err)); } }, - method: 'POST', - path: '/api/beats/enrollment_tokens', }); diff --git a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js index 88b7b7c3feb3a..621a6187693bd 100644 --- a/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js +++ b/x-pack/test/api_integration/apis/beats/assign_tags_to_beats.js @@ -5,10 +5,7 @@ */ import expect from 'expect.js'; -import { - ES_INDEX_NAME, - ES_TYPE_NAME -} from './constants'; +import { ES_INDEX_NAME, ES_TYPE_NAME } from './constants'; export default function ({ getService }) { const supertest = getService('supertest'); @@ -24,25 +21,19 @@ export default function ({ getService }) { it('should add a single tag to a single beat', async () => { const { body: apiResponse } = await supertest - .post( - '/api/beats/agents_tags/assignments' - ) + .post('/api/beats/agents_tags/assignments') .set('kbn-xsrf', 'xxx') .send({ - assignments: [ - { beat_id: 'bar', tag: 'production' } - ] + assignments: [{ beatId: 'bar', tag: 'production' }], }) .expect(200); - expect(apiResponse.assignments).to.eql([ - { status: 200, result: 'updated' } - ]); + expect(apiResponse.assignments).to.eql([{ status: 200, result: 'updated' }]); const esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:bar` + id: `beat:bar`, }); const beat = esResponse._source.beat; @@ -59,7 +50,7 @@ export default function ({ getService }) { esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:foo` + id: `beat:foo`, }); beat = esResponse._source.beat; @@ -67,26 +58,20 @@ export default function ({ getService }) { // Adding the existing tag const { body: apiResponse } = await supertest - .post( - '/api/beats/agents_tags/assignments' - ) + .post('/api/beats/agents_tags/assignments') .set('kbn-xsrf', 'xxx') .send({ - assignments: [ - { beat_id: 'foo', tag: 'production' } - ] + assignments: [{ beatId: 'foo', tag: 'production' }], }) .expect(200); - expect(apiResponse.assignments).to.eql([ - { status: 200, result: 'updated' } - ]); + expect(apiResponse.assignments).to.eql([{ status: 200, result: 'updated' }]); // After adding the existing tag esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:foo` + id: `beat:foo`, }); beat = esResponse._source.beat; @@ -95,21 +80,19 @@ export default function ({ getService }) { it('should add a single tag to a multiple beats', async () => { const { body: apiResponse } = await supertest - .post( - '/api/beats/agents_tags/assignments' - ) + .post('/api/beats/agents_tags/assignments') .set('kbn-xsrf', 'xxx') .send({ assignments: [ - { beat_id: 'foo', tag: 'development' }, - { beat_id: 'bar', tag: 'development' } - ] + { beatId: 'foo', tag: 'development' }, + { beatId: 'bar', tag: 'development' }, + ], }) .expect(200); expect(apiResponse.assignments).to.eql([ { status: 200, result: 'updated' }, - { status: 200, result: 'updated' } + { status: 200, result: 'updated' }, ]); let esResponse; @@ -119,7 +102,7 @@ export default function ({ getService }) { esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:foo` + id: `beat:foo`, }); beat = esResponse._source.beat; @@ -129,7 +112,7 @@ export default function ({ getService }) { esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:bar` + id: `beat:bar`, }); beat = esResponse._source.beat; @@ -138,27 +121,25 @@ export default function ({ getService }) { it('should add multiple tags to a single beat', async () => { const { body: apiResponse } = await supertest - .post( - '/api/beats/agents_tags/assignments' - ) + .post('/api/beats/agents_tags/assignments') .set('kbn-xsrf', 'xxx') .send({ assignments: [ - { beat_id: 'bar', tag: 'development' }, - { beat_id: 'bar', tag: 'production' } - ] + { beatId: 'bar', tag: 'development' }, + { beatId: 'bar', tag: 'production' }, + ], }) .expect(200); expect(apiResponse.assignments).to.eql([ { status: 200, result: 'updated' }, - { status: 200, result: 'updated' } + { status: 200, result: 'updated' }, ]); const esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:bar` + id: `beat:bar`, }); const beat = esResponse._source.beat; @@ -167,21 +148,19 @@ export default function ({ getService }) { it('should add multiple tags to a multiple beats', async () => { const { body: apiResponse } = await supertest - .post( - '/api/beats/agents_tags/assignments' - ) + .post('/api/beats/agents_tags/assignments') .set('kbn-xsrf', 'xxx') .send({ assignments: [ - { beat_id: 'foo', tag: 'development' }, - { beat_id: 'bar', tag: 'production' } - ] + { beatId: 'foo', tag: 'development' }, + { beatId: 'bar', tag: 'production' }, + ], }) .expect(200); expect(apiResponse.assignments).to.eql([ { status: 200, result: 'updated' }, - { status: 200, result: 'updated' } + { status: 200, result: 'updated' }, ]); let esResponse; @@ -191,7 +170,7 @@ export default function ({ getService }) { esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:foo` + id: `beat:foo`, }); beat = esResponse._source.beat; @@ -201,7 +180,7 @@ export default function ({ getService }) { esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:bar` + id: `beat:bar`, }); beat = esResponse._source.beat; @@ -212,19 +191,15 @@ export default function ({ getService }) { const nonExistentBeatId = chance.word(); const { body: apiResponse } = await supertest - .post( - '/api/beats/agents_tags/assignments' - ) + .post('/api/beats/agents_tags/assignments') .set('kbn-xsrf', 'xxx') .send({ - assignments: [ - { beat_id: nonExistentBeatId, tag: 'production' } - ] + assignments: [{ beatId: nonExistentBeatId, tag: 'production' }], }) .expect(200); expect(apiResponse.assignments).to.eql([ - { status: 404, result: `Beat ${nonExistentBeatId} not found` } + { status: 404, result: `Beat ${nonExistentBeatId} not found` }, ]); }); @@ -232,25 +207,21 @@ export default function ({ getService }) { const nonExistentTag = chance.word(); const { body: apiResponse } = await supertest - .post( - '/api/beats/agents_tags/assignments' - ) + .post('/api/beats/agents_tags/assignments') .set('kbn-xsrf', 'xxx') .send({ - assignments: [ - { beat_id: 'bar', tag: nonExistentTag } - ] + assignments: [{ beatID: 'bar', tag: nonExistentTag }], }) .expect(200); expect(apiResponse.assignments).to.eql([ - { status: 404, result: `Tag ${nonExistentTag} not found` } + { status: 404, result: `Tag ${nonExistentTag} not found` }, ]); const esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:bar` + id: `beat:bar`, }); const beat = esResponse._source.beat; @@ -262,25 +233,21 @@ export default function ({ getService }) { const nonExistentTag = chance.word(); const { body: apiResponse } = await supertest - .post( - '/api/beats/agents_tags/assignments' - ) + .post('/api/beats/agents_tags/assignments') .set('kbn-xsrf', 'xxx') .send({ - assignments: [ - { beat_id: nonExistentBeatId, tag: nonExistentTag } - ] + assignments: [{ beatID: nonExistentBeatId, tag: nonExistentTag }], }) .expect(200); expect(apiResponse.assignments).to.eql([ - { status: 404, result: `Beat ${nonExistentBeatId} and tag ${nonExistentTag} not found` } + { status: 404, result: `Beat ${nonExistentBeatId} and tag ${nonExistentTag} not found` }, ]); const esResponse = await es.get({ index: ES_INDEX_NAME, type: ES_TYPE_NAME, - id: `beat:bar` + id: `beat:bar`, }); const beat = esResponse._source.beat;