diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_index.test.ts b/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_index.test.ts index ab71d8e8611e8..73180ca093e2a 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_index.test.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_index.test.ts @@ -6,7 +6,7 @@ */ import { ByteSizeValue } from '@kbn/config-schema'; -import { IScopedClusterClient } from '@kbn/core/server'; +import { IScopedClusterClient, Logger } from '@kbn/core/server'; import { fetchConnectorByIndexName } from '@kbn/search-connectors'; @@ -47,6 +47,10 @@ describe('fetchIndex lib function', () => { jest.clearAllMocks(); }); + const logger = { + error: jest.fn(), + } as any as Logger; + const statsResponse = { indices: { index_name: { @@ -101,7 +105,7 @@ describe('fetchIndex lib function', () => { mockClient.asCurrentUser.indices.stats.mockImplementation(() => Promise.resolve(statsResponse)); await expect( - fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name') + fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name', logger) ).resolves.toEqual(result); }); @@ -125,7 +129,7 @@ describe('fetchIndex lib function', () => { mockClient.asCurrentUser.indices.stats.mockImplementation(() => Promise.resolve(statsResponse)); await expect( - fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name') + fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name', logger) ).resolves.toEqual({ ...result, connector: { doc: 'doc', service_type: 'some-service-type' }, @@ -141,7 +145,7 @@ describe('fetchIndex lib function', () => { mockClient.asCurrentUser.indices.stats.mockImplementation(() => Promise.resolve(statsResponse)); await expect( - fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name') + fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name', logger) ).rejects.toEqual(new Error('404')); }); it('should throw a 404 error if the indexStats cannot be fonud', async () => { @@ -158,7 +162,7 @@ describe('fetchIndex lib function', () => { ); await expect( - fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name') + fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name', logger) ).rejects.toEqual(new Error('404')); }); it('should throw a 404 error if the index stats indices cannot be fonud', async () => { @@ -173,7 +177,7 @@ describe('fetchIndex lib function', () => { mockClient.asCurrentUser.indices.stats.mockImplementation(() => Promise.resolve({})); await expect( - fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name') + fetchIndex(mockClient as unknown as IScopedClusterClient, 'index_name', logger) ).rejects.toEqual(new Error('404')); }); }); diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_index.ts b/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_index.ts index c1113807e1fff..5a513bfa378d2 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_index.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_index.ts @@ -5,11 +5,10 @@ * 2.0. */ -import { IScopedClusterClient } from '@kbn/core/server'; - -import {} from '../..'; +import { IScopedClusterClient, Logger } from '@kbn/core/server'; import { + Connector, CONNECTORS_JOBS_INDEX, ConnectorSyncJobDocument, fetchConnectorByIndexName, @@ -60,7 +59,8 @@ const hasInProgressSyncs = async ( export const fetchIndex = async ( client: IScopedClusterClient, - index: string + index: string, + logger: Logger ): Promise => { const indexDataResult = await client.asCurrentUser.indices.get({ index }); const indexData = indexDataResult[index]; @@ -72,8 +72,12 @@ export const fetchIndex = async ( throw new Error('404'); } const indexStats = indices[index]; - - const connector = await fetchConnectorByIndexName(client.asCurrentUser, index); + let connector: Connector | undefined; + try { + connector = await fetchConnectorByIndexName(client.asCurrentUser, index); + } catch (error) { + logger.error(`Error fetching connector for index ${index}: ${error}`); + } const hasInProgressSyncsResult = connector ? await hasInProgressSyncs(client, connector.id) : { inProgress: false, pending: false }; diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_unattached_indices.ts b/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_unattached_indices.ts index 2adbe070d0c80..b3bcb812496c3 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_unattached_indices.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/lib/indices/fetch_unattached_indices.ts @@ -6,7 +6,7 @@ */ import { IScopedClusterClient } from '@kbn/core/server'; -import { fetchConnectors } from '@kbn/search-connectors'; +import { Connector, fetchConnectors } from '@kbn/search-connectors'; import { isNotNullish } from '../../../common/utils/is_not_nullish'; @@ -22,7 +22,12 @@ export const fetchUnattachedIndices = async ( totalResults: number; }> => { const { indexNames } = await getUnattachedIndexData(client, searchQuery); - const connectors = await fetchConnectors(client.asCurrentUser, indexNames); + let connectors: Connector[] = []; + try { + connectors = await fetchConnectors(client.asCurrentUser, indexNames); + } catch (error) { + connectors = []; + } const connectedIndexNames = [...connectors.map((con) => con.index_name).filter(isNotNullish)]; diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/lib/pipelines/get_index_pipeline.ts b/x-pack/solutions/search/plugins/enterprise_search/server/lib/pipelines/get_index_pipeline.ts index 54a916898740e..61c3b678690ec 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/lib/pipelines/get_index_pipeline.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/lib/pipelines/get_index_pipeline.ts @@ -18,7 +18,7 @@ export const getIndexPipelineParameters = async ( // we want to throw the error if getDefaultPipeline() fails so we're not catching it on purpose const [defaultPipeline, connector, customPipelineResp] = await Promise.all([ getDefaultPipeline(client), - fetchConnectorByIndexName(client.asCurrentUser, indexName), + fetchConnectorByIndexName(client.asCurrentUser, indexName).catch(() => null), client.asCurrentUser.ingest .getPipeline({ id: `${indexName}`, diff --git a/x-pack/solutions/search/plugins/enterprise_search/server/routes/enterprise_search/indices.ts b/x-pack/solutions/search/plugins/enterprise_search/server/routes/enterprise_search/indices.ts index b38d0fd0e5218..f2832d8d6e46b 100644 --- a/x-pack/solutions/search/plugins/enterprise_search/server/routes/enterprise_search/indices.ts +++ b/x-pack/solutions/search/plugins/enterprise_search/server/routes/enterprise_search/indices.ts @@ -19,6 +19,7 @@ import { deleteConnectorSecret, deleteConnectorById, updateConnectorIndexName, + Connector, } from '@kbn/search-connectors'; import { fetchConnectorByIndexName, @@ -119,7 +120,13 @@ export function registerIndexRoutes({ router, log, ml }: RouteDependencies) { from, size ); - const connectors = await fetchConnectors(client.asCurrentUser, indexNames); + let connectors: Connector[] = []; + // If the user doesn't have permissions, fetchConnectors will error out. We still want to return indices in that case. + try { + connectors = await fetchConnectors(client.asCurrentUser, indexNames); + } catch { + connectors = []; + } const enrichedIndices = indices.map((index) => ({ ...index, connector: connectors.find((connector) => connector.index_name === index.name), @@ -155,7 +162,7 @@ export function registerIndexRoutes({ router, log, ml }: RouteDependencies) { const { client } = (await context.core).elasticsearch; try { - const index = await fetchIndex(client, indexName); + const index = await fetchIndex(client, indexName, log); return response.ok({ body: index, headers: { 'content-type': 'application/json' }, @@ -189,7 +196,13 @@ export function registerIndexRoutes({ router, log, ml }: RouteDependencies) { const { client } = (await context.core).elasticsearch; try { - const connector = await fetchConnectorByIndexName(client.asCurrentUser, indexName); + let connector: Connector | undefined; + // users without permissions to fetch connectors should still see a result + try { + connector = await fetchConnectorByIndexName(client.asCurrentUser, indexName); + } catch (error) { + log.error(`Error fetching connector for index ${indexName}: ${error}`); + } if (connector) { if (connector.service_type === CRAWLER_SERVICE_TYPE) { @@ -567,11 +580,13 @@ export function registerIndexRoutes({ router, log, ml }: RouteDependencies) { statusCode: 409, }); } - - const connector = await fetchConnectorByIndexName( - client.asCurrentUser, - request.body.index_name - ); + let connector: Connector | undefined; + // users without permissions to fetch connectors should still be able to create an index + try { + connector = await fetchConnectorByIndexName(client.asCurrentUser, indexName); + } catch (error) { + log.error(`Error fetching connector for index ${indexName}: ${error}`); + } if (connector) { return createError({