From 512fa305c4dfe623c5b1a7cf6cc1020120f133ad Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 3 Dec 2024 04:39:59 +1100 Subject: [PATCH] [8.x] Unauthorized route migration for routes owned by kibana-data-discovery (#198332) (#202519) # Backport This will backport the following commits from `main` to `8.x`: - [Unauthorized route migration for routes owned by kibana-data-discovery (#198332)](https://github.com/elastic/kibana/pull/198332) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) --- .../server/routes/field_preview.ts | 6 ++++ .../server/routes/preview_scripted_field.ts | 6 ++++ .../server/routes/resolve_index.ts | 6 ++++ .../internal/existing_indices.ts | 6 ++++ .../server/rest_api_routes/internal/fields.ts | 19 ++++++---- .../rest_api_routes/internal/fields_for.ts | 35 ++++++++++++++----- .../internal/has_data_views.ts | 6 ++++ .../rest_api_routes/internal/has_es_data.ts | 6 ++++ .../public/create_data_view.ts | 5 +++ .../public/default_data_view.ts | 11 ++++++ .../public/delete_data_view.ts | 5 +++ .../public/fields/update_fields.ts | 5 +++ .../rest_api_routes/public/get_data_view.ts | 6 ++++ .../rest_api_routes/public/get_data_views.ts | 6 ++++ .../public/has_user_data_view.ts | 6 ++++ .../runtime_fields/create_runtime_field.ts | 5 +++ .../runtime_fields/delete_runtime_field.ts | 5 +++ .../runtime_fields/get_runtime_field.ts | 6 ++++ .../runtime_fields/put_runtime_field.ts | 5 +++ .../runtime_fields/update_runtime_field.ts | 5 +++ .../scripted_fields/create_scripted_field.ts | 5 +++ .../scripted_fields/delete_scripted_field.ts | 5 +++ .../scripted_fields/get_scripted_field.ts | 6 ++++ .../scripted_fields/put_scripted_field.ts | 5 +++ .../scripted_fields/update_scripted_field.ts | 5 +++ .../rest_api_routes/public/swap_references.ts | 8 +++++ .../public/update_data_view.ts | 5 +++ .../__snapshots__/oss_features.test.ts.snap | 6 ++++ .../plugins/features/server/oss_features.ts | 1 + 29 files changed, 191 insertions(+), 15 deletions(-) diff --git a/src/plugins/data_view_field_editor/server/routes/field_preview.ts b/src/plugins/data_view_field_editor/server/routes/field_preview.ts index 9ddb0bf491fdb..8d585a7688714 100644 --- a/src/plugins/data_view_field_editor/server/routes/field_preview.ts +++ b/src/plugins/data_view_field_editor/server/routes/field_preview.ts @@ -51,6 +51,12 @@ export const registerFieldPreviewRoute = ({ router }: RouteDependencies): void = router.versioned.post({ path, access: 'internal' }).addVersion( { version: '1', + security: { + authz: { + enabled: false, + reason: 'Authorization provided by Elasticsearch', + }, + }, validate: { request: { body: bodySchema, diff --git a/src/plugins/data_view_management/server/routes/preview_scripted_field.ts b/src/plugins/data_view_management/server/routes/preview_scripted_field.ts index 71df0d5033a11..f5384bedce956 100644 --- a/src/plugins/data_view_management/server/routes/preview_scripted_field.ts +++ b/src/plugins/data_view_management/server/routes/preview_scripted_field.ts @@ -14,6 +14,12 @@ export function registerPreviewScriptedFieldRoute(router: IRouter): void { router.post( { path: '/internal/index-pattern-management/preview_scripted_field', + security: { + authz: { + enabled: false, + reason: 'Authorization provided by Elasticsearch', + }, + }, validate: { body: schema.object({ index: schema.string(), diff --git a/src/plugins/data_view_management/server/routes/resolve_index.ts b/src/plugins/data_view_management/server/routes/resolve_index.ts index c6b054182b1c4..f51027e55f9ca 100644 --- a/src/plugins/data_view_management/server/routes/resolve_index.ts +++ b/src/plugins/data_view_management/server/routes/resolve_index.ts @@ -15,6 +15,12 @@ export function registerResolveIndexRoute(router: IRouter): void { router.get( { path: '/internal/index-pattern-management/resolve_index/{query}', + security: { + authz: { + enabled: false, + reason: 'Authorization provided by Elasticsearch', + }, + }, validate: { params: schema.object({ query: schema.string(), diff --git a/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts b/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts index 5471ddb5dfedd..cf7806d76a4be 100644 --- a/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts +++ b/src/plugins/data_views/server/rest_api_routes/internal/existing_indices.ts @@ -60,6 +60,12 @@ export const registerExistingIndicesPath = (router: IRouter): void => { .addVersion( { version, + security: { + authz: { + enabled: false, + reason: 'This route is opted out from authorization', + }, + }, validate: { request: { query: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/internal/fields.ts b/src/plugins/data_views/server/rest_api_routes/internal/fields.ts index 7b13704f3c50a..3a884fbc8f3ee 100644 --- a/src/plugins/data_views/server/rest_api_routes/internal/fields.ts +++ b/src/plugins/data_views/server/rest_api_routes/internal/fields.ts @@ -146,10 +146,17 @@ export const registerFields = ( >, isRollupsEnabled: () => boolean ) => { - router.versioned - .get({ path, access: 'internal', enableQueryVersion: true }) - .addVersion( - { version: '1', validate: { request: { query: querySchema }, response: validate.response } }, - handler(isRollupsEnabled) - ); + router.versioned.get({ path, access: 'internal', enableQueryVersion: true }).addVersion( + { + version: '1', + security: { + authz: { + enabled: false, + reason: 'Authorization provided by Elasticsearch', + }, + }, + validate: { request: { query: querySchema }, response: validate.response }, + }, + handler(isRollupsEnabled) + ); }; diff --git a/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts b/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts index 7ff9f3ee9fede..d444d6f5131f1 100644 --- a/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts +++ b/src/plugins/data_views/server/rest_api_routes/internal/fields_for.ts @@ -9,7 +9,7 @@ import { estypes } from '@elastic/elasticsearch'; import { schema } from '@kbn/config-schema'; -import { IRouter, RequestHandler, StartServicesAccessor } from '@kbn/core/server'; +import type { IRouter, RequestHandler, RouteAuthz, StartServicesAccessor } from '@kbn/core/server'; import { VersionedRouteValidation } from '@kbn/core-http-server'; import { INITIAL_REST_VERSION_INTERNAL as version } from '../../constants'; import { IndexPatternsFetcher } from '../../fetcher'; @@ -217,14 +217,31 @@ export const registerFieldForWildcard = ( isRollupsEnabled: () => boolean ) => { const configuredHandler = handler(isRollupsEnabled); + const authz: RouteAuthz = { enabled: false, reason: 'Authorization provided by Elasticsearch' }; // handler - router.versioned.put({ path, access }).addVersion({ version, validate }, configuredHandler); - router.versioned.post({ path, access }).addVersion({ version, validate }, configuredHandler); - router.versioned - .get({ path, access }) - .addVersion( - { version, validate: { request: { query: querySchema }, response: validate.response } }, - configuredHandler - ); + router.versioned.put({ path, access }).addVersion( + { + version, + security: { authz }, + validate, + }, + configuredHandler + ); + router.versioned.post({ path, access }).addVersion( + { + version, + security: { authz }, + validate, + }, + configuredHandler + ); + router.versioned.get({ path, access }).addVersion( + { + version, + security: { authz }, + validate: { request: { query: querySchema }, response: validate.response }, + }, + configuredHandler + ); }; diff --git a/src/plugins/data_views/server/rest_api_routes/internal/has_data_views.ts b/src/plugins/data_views/server/rest_api_routes/internal/has_data_views.ts index a03da883594a3..4db1fce3a2040 100644 --- a/src/plugins/data_views/server/rest_api_routes/internal/has_data_views.ts +++ b/src/plugins/data_views/server/rest_api_routes/internal/has_data_views.ts @@ -45,6 +45,12 @@ export const registerHasDataViewsRoute = (router: IRouter): void => { .addVersion( { version: '1', + security: { + authz: { + enabled: false, + reason: 'Authorization provided by saved objects client', + }, + }, validate: { response: { 200: { diff --git a/src/plugins/data_views/server/rest_api_routes/internal/has_es_data.ts b/src/plugins/data_views/server/rest_api_routes/internal/has_es_data.ts index 72b2e508ba529..f9907e55f49b6 100644 --- a/src/plugins/data_views/server/rest_api_routes/internal/has_es_data.ts +++ b/src/plugins/data_views/server/rest_api_routes/internal/has_es_data.ts @@ -133,6 +133,12 @@ export const registerHasEsDataRoute = ( .addVersion( { version: '1', + security: { + authz: { + enabled: false, + reason: 'Authorization provided by Elasticsearch', + }, + }, validate: { response: { 200: { diff --git a/src/plugins/data_views/server/rest_api_routes/public/create_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/create_data_view.ts index 374c83880c019..68147df006ab4 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/create_data_view.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/create_data_view.ts @@ -61,6 +61,11 @@ const registerCreateDataViewRouteFactory = router.versioned.post({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { body: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/public/default_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/default_data_view.ts index 47700284d717b..9a5bf1f4ff361 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/default_data_view.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/default_data_view.ts @@ -73,6 +73,12 @@ const manageDefaultIndexPatternRoutesFactory = router.versioned.get({ path, access: 'public', description: getDescription }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + enabled: false, + reason: 'Authorization provided by saved objects client', + }, + }, validate: { request: {}, response: { @@ -110,6 +116,11 @@ const manageDefaultIndexPatternRoutesFactory = router.versioned.post({ path, access: 'public', description: postDescription }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { body: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/public/delete_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/delete_data_view.ts index 686c642257b31..cea1bd7e4e31e 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/delete_data_view.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/delete_data_view.ts @@ -53,6 +53,11 @@ const deleteIndexPatternRouteFactory = router.versioned.delete({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object( diff --git a/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts b/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts index eb59b0f8911bc..5f8faa2093ad5 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/fields/update_fields.ts @@ -131,6 +131,11 @@ const updateFieldsActionRouteFactory = (path: string, serviceKey: string, descri router.versioned.post({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object( diff --git a/src/plugins/data_views/server/rest_api_routes/public/get_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/get_data_view.ts index 6f4a7b7607a44..9b81de4913cb5 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/get_data_view.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/get_data_view.ts @@ -57,6 +57,12 @@ const getDataViewRouteFactory = router.versioned.get({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + enabled: false, + reason: 'Authorization provided by saved objects client', + }, + }, validate: { request: { params: schema.object( diff --git a/src/plugins/data_views/server/rest_api_routes/public/get_data_views.ts b/src/plugins/data_views/server/rest_api_routes/public/get_data_views.ts index 1add1096fe4ee..7ac2b3f1cb870 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/get_data_views.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/get_data_views.ts @@ -66,6 +66,12 @@ const getDataViewsRouteFactory = router.versioned.get({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + enabled: false, + reason: 'Authorization provided by saved objects client', + }, + }, validate: { request: {}, response: { 200: { body: responseValidation } }, diff --git a/src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts index 026b39dfbbf2a..62117555259f8 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/has_user_data_view.ts @@ -46,6 +46,12 @@ const hasUserDataViewRouteFactory = router.versioned.get({ path, access: 'internal' }).addVersion( { version: '1', + security: { + authz: { + enabled: false, + reason: 'Authorization provided by saved objects client', + }, + }, validate: { request: {}, response: { diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts index 301891642b2a7..2419082086daa 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/create_runtime_field.ts @@ -82,6 +82,11 @@ const runtimeCreateFieldRouteFactory = router.versioned.post({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts index 92e295f874aa7..d12aeabccc312 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/delete_runtime_field.ts @@ -65,6 +65,11 @@ const deleteRuntimeFieldRouteFactory = router.versioned.delete({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts index 574320c4e95d9..65f9af3c4fe01 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/get_runtime_field.ts @@ -73,6 +73,12 @@ const getRuntimeFieldRouteFactory = router.versioned.get({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + enabled: false, + reason: 'Authorization provided by saved objects client', + }, + }, validate: { request: { params: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts index cc122bb1da750..620e1fec6cca1 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/put_runtime_field.ts @@ -81,6 +81,11 @@ const putRuntimeFieldRouteFactory = router.versioned.put({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts index 612eebac89787..cd5c196e0e4f8 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/runtime_fields/update_runtime_field.ts @@ -81,6 +81,11 @@ const updateRuntimeFieldRouteFactory = router.versioned.post({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts index a826237b4b65e..829b5aa29c686 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/create_scripted_field.ts @@ -31,6 +31,11 @@ export const registerCreateScriptedFieldRoute = ( .addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object( diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/delete_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/delete_scripted_field.ts index e2d4285524825..66790d0d7f5e7 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/delete_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/delete_scripted_field.ts @@ -32,6 +32,11 @@ export const registerDeleteScriptedFieldRoute = ( .addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object( diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts index 18e5239715405..ba1b275ba5604 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/get_scripted_field.ts @@ -31,6 +31,12 @@ export const registerGetScriptedFieldRoute = ( .addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + enabled: false, + reason: 'Authorization provided by saved objects client', + }, + }, validate: { request: { params: schema.object( diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts index 0860804aa6789..d6c8b534dbd84 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/put_scripted_field.ts @@ -31,6 +31,11 @@ export const registerPutScriptedFieldRoute = ( .addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object( diff --git a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts index be42dd4787373..2ff837728d091 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/scripted_fields/update_scripted_field.ts @@ -36,6 +36,11 @@ export const registerUpdateScriptedFieldRoute = ( .addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object( diff --git a/src/plugins/data_views/server/rest_api_routes/public/swap_references.ts b/src/plugins/data_views/server/rest_api_routes/public/swap_references.ts index f40932137e3b3..52faad19da0eb 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/swap_references.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/swap_references.ts @@ -70,6 +70,14 @@ export const swapReferencesRoute = router.versioned.post({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + enabled: false, + // We don't use the indexPatterns:manage privilege for this route because it can be used for saved object + // types other than index-pattern + reason: 'Authorization provided by saved objects client', + }, + }, validate: { request: { body: schema.object({ diff --git a/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts b/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts index 51d7056ae2a2d..15e64ba05a340 100644 --- a/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts +++ b/src/plugins/data_views/server/rest_api_routes/public/update_data_view.ts @@ -147,6 +147,11 @@ const updateDataViewRouteFactory = router.versioned.post({ path, access: 'public', description }).addVersion( { version: INITIAL_REST_VERSION, + security: { + authz: { + requiredPrivileges: ['indexPatterns:manage'], + }, + }, validate: { request: { params: schema.object( diff --git a/x-pack/plugins/features/server/__snapshots__/oss_features.test.ts.snap b/x-pack/plugins/features/server/__snapshots__/oss_features.test.ts.snap index b8df9e9c2117b..b5614562f18a4 100644 --- a/x-pack/plugins/features/server/__snapshots__/oss_features.test.ts.snap +++ b/x-pack/plugins/features/server/__snapshots__/oss_features.test.ts.snap @@ -881,6 +881,9 @@ exports[`buildOSSFeatures with a basic license returns the indexPatterns feature Array [ Object { "privilege": Object { + "api": Array [ + "indexPatterns:manage", + ], "app": Array [ "kibana", ], @@ -1520,6 +1523,9 @@ exports[`buildOSSFeatures with a enterprise license returns the indexPatterns fe Array [ Object { "privilege": Object { + "api": Array [ + "indexPatterns:manage", + ], "app": Array [ "kibana", ], diff --git a/x-pack/plugins/features/server/oss_features.ts b/x-pack/plugins/features/server/oss_features.ts index 19001fe19547e..0f243e7e6bda8 100644 --- a/x-pack/plugins/features/server/oss_features.ts +++ b/x-pack/plugins/features/server/oss_features.ts @@ -401,6 +401,7 @@ export const buildOSSFeatures = ({ read: [], }, ui: ['save'], + api: ['indexPatterns:manage'], }, read: { app: ['kibana'],