From 724a3b22f30f025fd20ab575108c5df99aa93b1f Mon Sep 17 00:00:00 2001 From: Viduni Wickramarachchi Date: Thu, 28 Nov 2024 12:20:31 -0500 Subject: [PATCH] [Obs AI Assistant] Add security configs to API (#201439) ## Summary ### Problem The API `/internal/observability/assistant/alert_details_contextual_insights` does not provide explicit authorization settings. ### Solution Add access privileges (`ai_assistant`) to the above API ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../server/routes/assistant/route.ts | 6 +++- .../observability/server/routes/types.ts | 2 +- .../trial/tests/obs_alert_details_context.ts | 36 +++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability/server/routes/assistant/route.ts b/x-pack/plugins/observability_solution/observability/server/routes/assistant/route.ts index f5c6c393371c5..7b224dc92ade4 100644 --- a/x-pack/plugins/observability_solution/observability/server/routes/assistant/route.ts +++ b/x-pack/plugins/observability_solution/observability/server/routes/assistant/route.ts @@ -12,9 +12,13 @@ import { createObservabilityServerRoute } from '../create_observability_server_r const getObservabilityAlertDetailsContextRoute = createObservabilityServerRoute({ endpoint: 'GET /internal/observability/assistant/alert_details_contextual_insights', options: { - tags: [], access: 'internal', }, + security: { + authz: { + requiredPrivileges: ['ai_assistant'], + }, + }, params: t.type({ query: alertDetailsContextRt, }), diff --git a/x-pack/plugins/observability_solution/observability/server/routes/types.ts b/x-pack/plugins/observability_solution/observability/server/routes/types.ts index 111bc4e714119..1b189e1233b49 100644 --- a/x-pack/plugins/observability_solution/observability/server/routes/types.ts +++ b/x-pack/plugins/observability_solution/observability/server/routes/types.ts @@ -24,7 +24,7 @@ export interface ObservabilityRouteHandlerResources { } export interface ObservabilityRouteCreateOptions { - tags: string[]; + tags?: string[]; access?: 'public' | 'internal'; } diff --git a/x-pack/test/observability_api_integration/trial/tests/obs_alert_details_context.ts b/x-pack/test/observability_api_integration/trial/tests/obs_alert_details_context.ts index 608f44e18b34a..31f2bb5e3466e 100644 --- a/x-pack/test/observability_api_integration/trial/tests/obs_alert_details_context.ts +++ b/x-pack/test/observability_api_integration/trial/tests/obs_alert_details_context.ts @@ -17,6 +17,8 @@ export default function ApiTest({ getService }: ObsFtrProviderContext) { const obsApiClient = getService('obsApiClient'); const apmSynthtraceClient = getService('apmSynthtraceEsClient'); const logSynthtraceClient = getService('logSynthtraceEsClient'); + const security = getService('security'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('fetching observability alerts details context for AI assistant contextual insights', () => { const start = moment().subtract(10, 'minutes').valueOf(); @@ -511,5 +513,39 @@ export default function ApiTest({ getService }: ObsFtrProviderContext) { await apmSynthtraceClient.clean(); await logSynthtraceClient.clean(); } + + describe('security roles and access privileges', () => { + it('is not available to unauthorized users', async () => { + const UNAUTHORIZED_USERNAME = 'UNAUTHORIZED_USER'; + const UNAUTHORIZED_USER_PASSWORD = 'UNAUTHORIZED_USER_PASSWORD'; + + // Create a user with no privileges + await security.user.create(UNAUTHORIZED_USERNAME, { + password: UNAUTHORIZED_USER_PASSWORD, + roles: [], + full_name: 'Unauthorized Test User', + }); + + try { + // Make a request to the target API with insufficient privileges + await supertestWithoutAuth + .get('/internal/observability/assistant/alert_details_contextual_insights') + .auth(UNAUTHORIZED_USERNAME, UNAUTHORIZED_USER_PASSWORD) + .query({ alertId: 'test-alert-id' }) + .set('kbn-xsrf', 'true') + .expect(403) + .then(({ body }: any) => { + expect(body).to.eql({ + statusCode: 403, + error: 'Forbidden', + message: + 'API [GET /internal/observability/assistant/alert_details_contextual_insights?alertId=test-alert-id] is unauthorized for user, this action is granted by the Kibana privileges [ai_assistant]', + }); + }); + } finally { + await security.user.delete(UNAUTHORIZED_USERNAME); + } + }); + }); }); }