From aa8d8946095b9868f0b9b5ddbbd918c2b3060ce6 Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 30 Mar 2020 09:59:33 -0400 Subject: [PATCH 1/3] [Fleet] Fix find by apiKeyId escaping --- .../ingest_manager/server/services/agents/crud.ts | 7 +++++-- .../ingest_manager/server/services/api_keys/index.ts | 7 ++++++- .../ingest_manager/server/services/saved_object.ts | 9 +++++++++ x-pack/test/api_integration/apis/fleet/agents/acks.ts | 3 +-- 4 files changed, 21 insertions(+), 5 deletions(-) create mode 100644 x-pack/plugins/ingest_manager/server/services/saved_object.ts diff --git a/x-pack/plugins/ingest_manager/server/services/agents/crud.ts b/x-pack/plugins/ingest_manager/server/services/agents/crud.ts index 41bd2476c99a1..ec270884e62b4 100644 --- a/x-pack/plugins/ingest_manager/server/services/agents/crud.ts +++ b/x-pack/plugins/ingest_manager/server/services/agents/crud.ts @@ -14,6 +14,7 @@ import { } from '../../constants'; import { AgentSOAttributes, Agent, AgentEventSOAttributes } from '../../types'; import { savedObjectToAgent } from './saved_objects'; +import { escapeSearchQueryPhrase } from '../saved_object'; export async function listAgents( soClient: SavedObjectsClientContract, @@ -72,14 +73,16 @@ export async function getAgentByAccessAPIKeyId( const response = await soClient.find({ type: AGENT_SAVED_OBJECT_TYPE, searchFields: ['access_api_key_id'], - search: accessAPIKeyId, + search: escapeSearchQueryPhrase(accessAPIKeyId), }); - const [agent] = response.saved_objects.map(savedObjectToAgent); if (!agent) { throw Boom.notFound('Agent not found'); } + if (agent.access_api_key_id !== accessAPIKeyId) { + throw new Error('Agent api key id is not matching'); + } if (!agent.active) { throw Boom.forbidden('Agent inactive'); } diff --git a/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts b/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts index 5c05d5612e200..02200ee6ee69b 100644 --- a/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts @@ -8,6 +8,7 @@ import { SavedObjectsClientContract, SavedObject, KibanaRequest } from 'src/core import { ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE } from '../../constants'; import { EnrollmentAPIKeySOAttributes, EnrollmentAPIKey } from '../../types'; import { createAPIKey } from './security'; +import { escapeSearchQueryPhrase } from '../saved_object'; export * from './enrollment_api_key'; @@ -70,10 +71,14 @@ export async function getEnrollmentAPIKeyById( await soClient.find({ type: ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE, searchFields: ['api_key_id'], - search: apiKeyId, + search: escapeSearchQueryPhrase(apiKeyId), }) ).saved_objects.map(_savedObjectToEnrollmentApiKey); + if (enrollmentAPIKey?.id !== apiKeyId) { + throw new Error('find enrollmentKeyById returned an incorrect key'); + } + return enrollmentAPIKey; } diff --git a/x-pack/plugins/ingest_manager/server/services/saved_object.ts b/x-pack/plugins/ingest_manager/server/services/saved_object.ts new file mode 100644 index 0000000000000..b676af2f906c4 --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/saved_object.ts @@ -0,0 +1,9 @@ +/* + * 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 function escapeSearchQueryPhrase(val: string) { + return `"${val.replace(/["]/g, '"')}"`; +} diff --git a/x-pack/test/api_integration/apis/fleet/agents/acks.ts b/x-pack/test/api_integration/apis/fleet/agents/acks.ts index db925813b90c4..a2eba2c23c39d 100644 --- a/x-pack/test/api_integration/apis/fleet/agents/acks.ts +++ b/x-pack/test/api_integration/apis/fleet/agents/acks.ts @@ -18,8 +18,7 @@ export default function(providerContext: FtrProviderContext) { const supertest = getSupertestWithoutAuth(providerContext); let apiKey: { id: string; api_key: string }; - // FLAKY: https://github.com/elastic/kibana/issues/60471 - describe.skip('fleet_agents_acks', () => { + describe('fleet_agents_acks', () => { before(async () => { await esArchiver.loadIfNeeded('fleet/agents'); From a1a1a219134db9a587b078d4679085c0a461da2a Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 30 Mar 2020 11:22:39 -0400 Subject: [PATCH 2/3] More docs and test --- .../server/services/saved_object.test.ts | 23 +++++++++++++++++++ .../server/services/saved_object.ts | 7 +++++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/ingest_manager/server/services/saved_object.test.ts diff --git a/x-pack/plugins/ingest_manager/server/services/saved_object.test.ts b/x-pack/plugins/ingest_manager/server/services/saved_object.test.ts new file mode 100644 index 0000000000000..9eb5dccb76ac5 --- /dev/null +++ b/x-pack/plugins/ingest_manager/server/services/saved_object.test.ts @@ -0,0 +1,23 @@ +/* + * 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 { escapeSearchQueryPhrase } from './saved_object'; + +describe('Saved object service', () => { + describe('escapeSearchQueryPhrase', () => { + it('should return value between quotes', () => { + const res = escapeSearchQueryPhrase('-test'); + + expect(res).toEqual('"-test"'); + }); + + it('should escape quotes', () => { + const res = escapeSearchQueryPhrase('test1"test2'); + + expect(res).toEqual(`"test1\"test2"`); + }); + }); +}); diff --git a/x-pack/plugins/ingest_manager/server/services/saved_object.ts b/x-pack/plugins/ingest_manager/server/services/saved_object.ts index b676af2f906c4..8fe7ffcdfc896 100644 --- a/x-pack/plugins/ingest_manager/server/services/saved_object.ts +++ b/x-pack/plugins/ingest_manager/server/services/saved_object.ts @@ -4,6 +4,11 @@ * you may not use this file except in compliance with the Elastic License. */ -export function escapeSearchQueryPhrase(val: string) { +/** + * Escape a value with double quote to use with saved object search + * Example: escapeSearchQueryPhrase('-test"toto') => '"-test\"toto""' + * @param val + */ +export function escapeSearchQueryPhrase(val: string): string { return `"${val.replace(/["]/g, '"')}"`; } From 999820e19305a4da3b275349ff01a582b6d0ed4e Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Mon, 30 Mar 2020 14:38:17 -0400 Subject: [PATCH 3/3] Fix typo --- x-pack/plugins/ingest_manager/server/services/api_keys/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts b/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts index 02200ee6ee69b..23f770c422370 100644 --- a/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts +++ b/x-pack/plugins/ingest_manager/server/services/api_keys/index.ts @@ -75,7 +75,7 @@ export async function getEnrollmentAPIKeyById( }) ).saved_objects.map(_savedObjectToEnrollmentApiKey); - if (enrollmentAPIKey?.id !== apiKeyId) { + if (enrollmentAPIKey?.api_key_id !== apiKeyId) { throw new Error('find enrollmentKeyById returned an incorrect key'); }