Skip to content

Commit

Permalink
[9.0] [Search] Don't error out on missing connectors permissions (#21…
Browse files Browse the repository at this point in the history
…2622) (#212763)

# Backport

This will backport the following commits from `main` to `9.0`:
- [[Search] Don't error out on missing connectors permissions
(#212622)](#212622)

<!--- Backport version: 9.6.6 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sorenlouv/backport)

<!--BACKPORT [{"author":{"name":"Sander
Philipse","email":"94373878+sphilipse@users.noreply.github.com"},"sourceCommit":{"committedDate":"2025-02-28T12:36:37Z","message":"[Search]
Don't error out on missing connectors permissions (#212622)\n\n##
Summary\n\nThis stops errors on missing connectors permissions when
fetching\nindices, which was preventing users without connectors
permissions but\nwith listing and write permissions to indices generally
from seeing\nindices in the Search UI.\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"7590205f9a9dd79c8a204eb75b69782503d30937","branchLabelMapping":{"^v9.1.0$":"main","^v8.19.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","Team:Search","backport:version","v8.18.0","v9.1.0","v8.19.0","v8.17.3"],"title":"[Search]
Don't error out on missing connectors
permissions","number":212622,"url":"https://github.com/elastic/kibana/pull/212622","mergeCommit":{"message":"[Search]
Don't error out on missing connectors permissions (#212622)\n\n##
Summary\n\nThis stops errors on missing connectors permissions when
fetching\nindices, which was preventing users without connectors
permissions but\nwith listing and write permissions to indices generally
from seeing\nindices in the Search UI.\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"7590205f9a9dd79c8a204eb75b69782503d30937"}},"sourceBranch":"main","suggestedTargetBranches":["9.0","8.18","8.x","8.17"],"targetPullRequestStates":[{"branch":"9.0","label":"v9.0.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.18","label":"v8.18.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v9.1.0","branchLabelMappingKey":"^v9.1.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/212622","number":212622,"mergeCommit":{"message":"[Search]
Don't error out on missing connectors permissions (#212622)\n\n##
Summary\n\nThis stops errors on missing connectors permissions when
fetching\nindices, which was preventing users without connectors
permissions but\nwith listing and write permissions to indices generally
from seeing\nindices in the Search UI.\n\n---------\n\nCo-authored-by:
kibanamachine
<42973632+kibanamachine@users.noreply.github.com>","sha":"7590205f9a9dd79c8a204eb75b69782503d30937"}},{"branch":"8.x","label":"v8.19.0","branchLabelMappingKey":"^v8.19.0$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"8.17","label":"v8.17.3","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Sander Philipse <94373878+sphilipse@users.noreply.github.com>
  • Loading branch information
kibanamachine and sphilipse authored Feb 28, 2025
1 parent ea80085 commit e32f93a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -47,6 +47,10 @@ describe('fetchIndex lib function', () => {
jest.clearAllMocks();
});

const logger = {
error: jest.fn(),
} as any as Logger;

const statsResponse = {
indices: {
index_name: {
Expand Down Expand Up @@ -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);
});

Expand All @@ -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' },
Expand All @@ -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 () => {
Expand All @@ -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 () => {
Expand All @@ -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'));
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -60,7 +59,8 @@ const hasInProgressSyncs = async (

export const fetchIndex = async (
client: IScopedClusterClient,
index: string
index: string,
logger: Logger
): Promise<ElasticsearchIndexWithIngestion> => {
const indexDataResult = await client.asCurrentUser.indices.get({ index });
const indexData = indexDataResult[index];
Expand All @@ -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 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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)];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
deleteConnectorSecret,
deleteConnectorById,
updateConnectorIndexName,
Connector,
} from '@kbn/search-connectors';
import {
fetchConnectorByIndexName,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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' },
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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({
Expand Down

0 comments on commit e32f93a

Please sign in to comment.