From 2a05ec9ff55c72c4818537ce59637966311d08b4 Mon Sep 17 00:00:00 2001 From: Mark Hopkin Date: Thu, 26 Aug 2021 16:47:11 +0100 Subject: [PATCH 1/4] [Fleet] Don't ignore "index: false" in integration index template (#110234) * fix: don't ignore index prop when falsey * test: add unit test for index false --- .../elasticsearch/template/template.test.ts | 20 +++++++++++++++++++ .../epm/elasticsearch/template/template.ts | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts index 10db955c52ee1..4c10d0e74dad7 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.test.ts @@ -174,6 +174,26 @@ describe('EPM template', () => { expect(template).toMatchSnapshot(path.basename(ymlPath)); }); + it('tests processing long field with index false', () => { + const longWithIndexFalseYml = ` +- name: longIndexFalse + type: long + index: false +`; + const longWithIndexFalseMapping = { + properties: { + longIndexFalse: { + type: 'long', + index: false, + }, + }, + }; + const fields: Field[] = safeLoad(longWithIndexFalseYml); + const processedFields = processFields(fields); + const mappings = generateMappings(processedFields); + expect(mappings).toEqual(longWithIndexFalseMapping); + }); + it('tests processing text field with multi fields', () => { const textWithMultiFieldsLiteralYml = ` - name: textWithMultiFields diff --git a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts index d4181201677c5..c999a135e2116 100644 --- a/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts +++ b/x-pack/plugins/fleet/server/services/epm/elasticsearch/template/template.ts @@ -277,7 +277,7 @@ function generateTextMapping(field: Field): IndexTemplateMapping { function getDefaultProperties(field: Field): Properties { const properties: Properties = {}; - if (field.index) { + if (field.index !== undefined) { properties.index = field.index; } if (field.doc_values) { From 00c9a76e0d814e568c1262246a02540808a4a9fb Mon Sep 17 00:00:00 2001 From: Anton Dosov Date: Thu, 26 Aug 2021 17:56:19 +0200 Subject: [PATCH 2/4] [fieldFormats] remove reliance on eslint-rule-no-export-all --- src/plugins/field_formats/common/index.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/field_formats/common/index.ts b/src/plugins/field_formats/common/index.ts index b6c58eb12d7cd..2e0aa82a67b30 100644 --- a/src/plugins/field_formats/common/index.ts +++ b/src/plugins/field_formats/common/index.ts @@ -51,5 +51,3 @@ export { IFieldFormat, FieldFormatsStartCommon, } from './types'; - -export * from './errors'; From 416d42a22a9d4880b37af82c3c9eca709126c5c6 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Thu, 26 Aug 2021 12:01:28 -0400 Subject: [PATCH 3/4] [Security Solution][RAC] Refix expand (#110236) --- .../timelines/public/components/t_grid/body/index.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx index e59d87d843478..f3220cfd8909e 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/body/index.tsx @@ -622,17 +622,12 @@ export const BodyComponent = React.memo( const rowData = rowIndex < data.length ? data[rowIndex].data : null; const header = columnHeaders.find((h) => h.id === columnId); const eventId = rowIndex < data.length ? data[rowIndex]._id : null; - const defaultStyles = useMemo( - () => ({ - overflow: 'hidden', - }), - [] - ); - setCellProps({ style: { ...defaultStyles } }); useEffect(() => { + const defaultStyles = { overflow: 'hidden' }; + setCellProps({ style: { ...defaultStyles } }); addBuildingBlockStyle(data[rowIndex].ecs, theme, setCellProps, defaultStyles); - }, [rowIndex, setCellProps, defaultStyles]); + }, [rowIndex, setCellProps]); if (rowData == null || header == null || eventId == null) { return null; From b15b3ce19ddcda9e91dd8c3d1369a9daeff64f64 Mon Sep 17 00:00:00 2001 From: "Christiane (Tina) Heiligers" Date: Thu, 26 Aug 2021 09:03:13 -0700 Subject: [PATCH 4/4] Fixes bugs for product check in update and delete (#109979) * Fixes bugs for product check in update and delete * Apply suggestions from code review --- .../service/lib/decorate_es_error.test.ts | 12 +++++++++ .../service/lib/decorate_es_error.ts | 6 +++++ .../service/lib/repository.test.js | 22 ++++++---------- .../saved_objects/service/lib/repository.ts | 25 ++++++------------- 4 files changed, 32 insertions(+), 33 deletions(-) diff --git a/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts b/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts index 9dd8959d49293..4e187e85f81a7 100644 --- a/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts +++ b/src/core/server/saved_objects/service/lib/decorate_es_error.test.ts @@ -109,6 +109,18 @@ describe('savedObjectsClient/decorateEsError', () => { expect(SavedObjectsErrorHelpers.isNotFoundError(genericError)).toBe(true); }); + it('makes NotFound errors generic NotFoundEsUnavailableError errors when response is from unsupported server', () => { + const error = new esErrors.ResponseError( + // explicitly override the headers + elasticsearchClientMock.createApiResponse({ statusCode: 404, headers: {} }) + ); + expect(SavedObjectsErrorHelpers.isNotFoundError(error)).toBe(false); + const genericError = decorateEsError(error); + expect(genericError).not.toBe(error); + expect(SavedObjectsErrorHelpers.isNotFoundError(genericError)).toBe(false); + expect(SavedObjectsErrorHelpers.isEsUnavailableError(genericError)).toBe(true); + }); + it('if saved objects index does not exist makes NotFound a SavedObjectsClient/generalError', () => { const error = new esErrors.ResponseError( elasticsearchClientMock.createApiResponse({ diff --git a/src/core/server/saved_objects/service/lib/decorate_es_error.ts b/src/core/server/saved_objects/service/lib/decorate_es_error.ts index e1aa1ab2f956d..016268ccdf9f4 100644 --- a/src/core/server/saved_objects/service/lib/decorate_es_error.ts +++ b/src/core/server/saved_objects/service/lib/decorate_es_error.ts @@ -8,6 +8,7 @@ import { errors as esErrors } from '@elastic/elasticsearch'; import { get } from 'lodash'; +import { isSupportedEsServer } from '../../../elasticsearch'; const responseErrors = { isServiceUnavailable: (statusCode: number) => statusCode === 503, @@ -69,6 +70,11 @@ export function decorateEsError(error: EsErrors) { if (match?.length > 0) { return SavedObjectsErrorHelpers.decorateIndexAliasNotFoundError(error, match[1]); } + // Throw EsUnavailable error if the 404 is not from elasticsearch + // Needed here to verify Product support for any non-ignored 404 responses from calls to ES + if (!isSupportedEsServer(error?.meta?.headers)) { + return SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(); + } return SavedObjectsErrorHelpers.createGenericNotFoundError(); } diff --git a/src/core/server/saved_objects/service/lib/repository.test.js b/src/core/server/saved_objects/service/lib/repository.test.js index d4d794c165fe2..427c28ceb326c 100644 --- a/src/core/server/saved_objects/service/lib/repository.test.js +++ b/src/core/server/saved_objects/service/lib/repository.test.js @@ -2439,27 +2439,19 @@ describe('SavedObjectsRepository', () => { it(`throws when ES is unable to find the document during delete`, async () => { client.delete.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { result: 'not_found' }, - {}, - {} - ) + elasticsearchClientMock.createSuccessTransportRequestPromise({ result: 'not_found' }) ); - await expectNotFoundEsUnavailableError(type, id); + await expectNotFoundError(type, id); expect(client.delete).toHaveBeenCalledTimes(1); }); it(`throws when ES is unable to find the index during delete`, async () => { client.delete.mockResolvedValueOnce( - elasticsearchClientMock.createSuccessTransportRequestPromise( - { - error: { type: 'index_not_found_exception' }, - }, - {}, - {} - ) + elasticsearchClientMock.createSuccessTransportRequestPromise({ + error: { type: 'index_not_found_exception' }, + }) ); - await expectNotFoundEsUnavailableError(type, id); + await expectNotFoundError(type, id); expect(client.delete).toHaveBeenCalledTimes(1); }); @@ -3430,7 +3422,7 @@ describe('SavedObjectsRepository', () => { client.get.mockResolvedValueOnce( elasticsearchClientMock.createSuccessTransportRequestPromise( { found: false }, - undefined, + { statusCode: 404 }, {} ) ); diff --git a/src/core/server/saved_objects/service/lib/repository.ts b/src/core/server/saved_objects/service/lib/repository.ts index c2ae6ebab00e9..7ce3a55d057eb 100644 --- a/src/core/server/saved_objects/service/lib/repository.ts +++ b/src/core/server/saved_objects/service/lib/repository.ts @@ -682,6 +682,10 @@ export class SavedObjectsRepository { { ignore: [404] } ); + if (isNotFoundFromUnsupportedServer({ statusCode, headers })) { + throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); + } + const deleted = body.result === 'deleted'; if (deleted) { return {}; @@ -690,15 +694,9 @@ export class SavedObjectsRepository { const deleteDocNotFound = body.result === 'not_found'; // @ts-expect-error @elastic/elasticsearch doesn't declare error on DeleteResponse const deleteIndexNotFound = body.error && body.error.type === 'index_not_found_exception'; - const esServerSupported = isSupportedEsServer(headers); if (deleteDocNotFound || deleteIndexNotFound) { - if (esServerSupported) { - // see "404s from missing index" above - throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); - } else { - // throw if we can't verify the response is from Elasticsearch - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); - } + // see "404s from missing index" above + throw SavedObjectsErrorHelpers.createGenericNotFoundError(type, id); } throw new Error( @@ -1084,7 +1082,7 @@ export class SavedObjectsRepository { ); const indexNotFound = statusCode === 404; // check if we have the elasticsearch header when index is not found and if we do, ensure it is Elasticsearch - if (!isFoundGetResponse(body) && !isSupportedEsServer(headers)) { + if (indexNotFound && !isSupportedEsServer(headers)) { throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); } if ( @@ -1331,15 +1329,6 @@ export class SavedObjectsRepository { _source_includes: ['namespace', 'namespaces', 'originId'], require_alias: true, }) - .then((res) => { - const indexNotFound = res.statusCode === 404; - const esServerSupported = isSupportedEsServer(res.headers); - // check if we have the elasticsearch header when index is not found and if we do, ensure it is Elasticsearch - if (indexNotFound && !esServerSupported) { - throw SavedObjectsErrorHelpers.createGenericNotFoundEsUnavailableError(type, id); - } - return res; - }) .catch((err) => { if (SavedObjectsErrorHelpers.isEsUnavailableError(err)) { throw err;