From 8248f495380d4802f032533a7d17af21bc54c5c3 Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Fri, 10 Jul 2020 06:22:42 -0600 Subject: [PATCH] [SIEM][Detection Engine][Lists] Adds read_privileges route for lists and list items (#71356) ## Summary * Adds a read_privileges for the list and list items. Run the script: get_privileges.sh API: ```ts GET /api/lists/privileges { "listItems": { "username": "yo", "has_all_requested": false, "cluster": { "monitor_ml": true, "manage_ccr": true, "manage_index_templates": true, "monitor_watcher": true, "monitor_transform": true, "read_ilm": true, "manage_api_key": true, "manage_security": true, "manage_own_api_key": false, "manage_saml": true, "all": true, "manage_ilm": true, "manage_ingest_pipelines": true, "read_ccr": true, "manage_rollup": true, "monitor": true, "manage_watcher": true, "manage": true, "manage_transform": true, "manage_token": true, "manage_ml": true, "manage_pipeline": true, "monitor_rollup": true, "transport_client": true, "create_snapshot": true }, "index": { ".lists-frank-default": { "all": true, "manage_ilm": true, "read": true, "create_index": true, "read_cross_cluster": true, "index": true, "monitor": true, "delete": true, "manage": true, "delete_index": true, "create_doc": true, "view_index_metadata": true, "create": true, "manage_follow_index": true, "manage_leader_index": true, "write": true } }, "application": {} }, "lists": { "username": "yo", "has_all_requested": false, "cluster": { "monitor_ml": true, "manage_ccr": true, "manage_index_templates": true, "monitor_watcher": true, "monitor_transform": true, "read_ilm": true, "manage_api_key": true, "manage_security": true, "manage_own_api_key": false, "manage_saml": true, "all": true, "manage_ilm": true, "manage_ingest_pipelines": true, "read_ccr": true, "manage_rollup": true, "monitor": true, "manage_watcher": true, "manage": true, "manage_transform": true, "manage_token": true, "manage_ml": true, "manage_pipeline": true, "monitor_rollup": true, "transport_client": true, "create_snapshot": true }, "index": { ".lists-frank-default": { "all": true, "manage_ilm": true, "read": true, "create_index": true, "read_cross_cluster": true, "index": true, "monitor": true, "delete": true, "manage": true, "delete_index": true, "create_doc": true, "view_index_metadata": true, "create": true, "manage_follow_index": true, "manage_leader_index": true, "write": true } }, "application": {} }, "is_authenticated": true } ``` ### Checklist We currently have not ported over patterns for the routes so we do not have sanity checks against this or other routes and no end point tests which is why the check box is not checked below at this point in time. We are implementing those tests during the feature freeze (hopefully) - [ ] [Unit or functional tests](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md#cross-browser-compatibility) were updated or added to match the most common scenarios --- x-pack/plugins/lists/common/constants.ts | 1 + x-pack/plugins/lists/server/plugin.ts | 2 +- .../lists/server/routes/init_routes.ts | 10 +++- .../server/routes/read_privileges_route.ts | 60 +++++++++++++++++++ .../lists/server/scripts/get_privileges.sh | 15 +++++ .../plugins/lists/server/siem_server_deps.ts | 1 + .../plugins/security_solution/server/index.ts | 1 + 7 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 x-pack/plugins/lists/server/routes/read_privileges_route.ts create mode 100755 x-pack/plugins/lists/server/scripts/get_privileges.sh diff --git a/x-pack/plugins/lists/common/constants.ts b/x-pack/plugins/lists/common/constants.ts index 6cb88b19483cef..af29b3aa53dedb 100644 --- a/x-pack/plugins/lists/common/constants.ts +++ b/x-pack/plugins/lists/common/constants.ts @@ -10,6 +10,7 @@ export const LIST_URL = '/api/lists'; export const LIST_INDEX = `${LIST_URL}/index`; export const LIST_ITEM_URL = `${LIST_URL}/items`; +export const LIST_PRIVILEGES_URL = `${LIST_URL}/privileges`; /** * Exception list routes diff --git a/x-pack/plugins/lists/server/plugin.ts b/x-pack/plugins/lists/server/plugin.ts index b4f2639f24923f..118bb2f927a645 100644 --- a/x-pack/plugins/lists/server/plugin.ts +++ b/x-pack/plugins/lists/server/plugin.ts @@ -48,7 +48,7 @@ export class ListPlugin core.http.registerRouteHandlerContext('lists', this.createRouteHandlerContext()); const router = core.http.createRouter(); - initRoutes(router, config); + initRoutes(router, config, plugins.security); return { getExceptionListClient: (savedObjectsClient, user): ExceptionListClient => { diff --git a/x-pack/plugins/lists/server/routes/init_routes.ts b/x-pack/plugins/lists/server/routes/init_routes.ts index ffd8afd54913f0..fef7f19f02df2d 100644 --- a/x-pack/plugins/lists/server/routes/init_routes.ts +++ b/x-pack/plugins/lists/server/routes/init_routes.ts @@ -6,8 +6,11 @@ import { IRouter } from 'kibana/server'; +import { SecurityPluginSetup } from '../../../security/server'; import { ConfigType } from '../config'; +import { readPrivilegesRoute } from './read_privileges_route'; + import { createExceptionListItemRoute, createExceptionListRoute, @@ -38,7 +41,11 @@ import { updateListRoute, } from '.'; -export const initRoutes = (router: IRouter, config: ConfigType): void => { +export const initRoutes = ( + router: IRouter, + config: ConfigType, + security: SecurityPluginSetup | null | undefined +): void => { // lists createListRoute(router); readListRoute(router); @@ -46,6 +53,7 @@ export const initRoutes = (router: IRouter, config: ConfigType): void => { deleteListRoute(router); patchListRoute(router); findListRoute(router); + readPrivilegesRoute(router, security); // list items createListItemRoute(router); diff --git a/x-pack/plugins/lists/server/routes/read_privileges_route.ts b/x-pack/plugins/lists/server/routes/read_privileges_route.ts new file mode 100644 index 00000000000000..892b6406a28ecc --- /dev/null +++ b/x-pack/plugins/lists/server/routes/read_privileges_route.ts @@ -0,0 +1,60 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { IRouter } from 'kibana/server'; +import { merge } from 'lodash/fp'; + +import { SecurityPluginSetup } from '../../../security/server'; +import { LIST_PRIVILEGES_URL } from '../../common/constants'; +import { buildSiemResponse, readPrivileges, transformError } from '../siem_server_deps'; + +import { getListClient } from './utils'; + +export const readPrivilegesRoute = ( + router: IRouter, + security: SecurityPluginSetup | null | undefined +): void => { + router.get( + { + options: { + tags: ['access:lists'], + }, + path: LIST_PRIVILEGES_URL, + validate: false, + }, + async (context, request, response) => { + const siemResponse = buildSiemResponse(response); + try { + const clusterClient = context.core.elasticsearch.legacy.client; + const lists = getListClient(context); + const clusterPrivilegesLists = await readPrivileges( + clusterClient.callAsCurrentUser, + lists.getListIndex() + ); + const clusterPrivilegesListItems = await readPrivileges( + clusterClient.callAsCurrentUser, + lists.getListIndex() + ); + const privileges = merge( + { + listItems: clusterPrivilegesListItems, + lists: clusterPrivilegesLists, + }, + { + is_authenticated: security?.authc.isAuthenticated(request) ?? false, + } + ); + return response.ok({ body: privileges }); + } catch (err) { + const error = transformError(err); + return siemResponse.error({ + body: error.message, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/lists/server/scripts/get_privileges.sh b/x-pack/plugins/lists/server/scripts/get_privileges.sh new file mode 100755 index 00000000000000..4c02747f3c56c8 --- /dev/null +++ b/x-pack/plugins/lists/server/scripts/get_privileges.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# +# Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one +# or more contributor license agreements. Licensed under the Elastic License; +# you may not use this file except in compliance with the Elastic License. +# + +set -e +./check_env_variables.sh + +# Example: ./get_privileges.sh +curl -s -k \ + -u ${ELASTICSEARCH_USERNAME}:${ELASTICSEARCH_PASSWORD} \ + -X GET ${KIBANA_URL}${SPACE_URL}/api/lists/privileges | jq . diff --git a/x-pack/plugins/lists/server/siem_server_deps.ts b/x-pack/plugins/lists/server/siem_server_deps.ts index 87a623c7a18924..324103b7fb50de 100644 --- a/x-pack/plugins/lists/server/siem_server_deps.ts +++ b/x-pack/plugins/lists/server/siem_server_deps.ts @@ -17,4 +17,5 @@ export { createBootstrapIndex, getIndexExists, buildRouteValidation, + readPrivileges, } from '../../security_solution/server'; diff --git a/x-pack/plugins/security_solution/server/index.ts b/x-pack/plugins/security_solution/server/index.ts index 06b35213b4713a..7b84c531dd376d 100644 --- a/x-pack/plugins/security_solution/server/index.ts +++ b/x-pack/plugins/security_solution/server/index.ts @@ -54,3 +54,4 @@ export { createBootstrapIndex } from './lib/detection_engine/index/create_bootst export { getIndexExists } from './lib/detection_engine/index/get_index_exists'; export { buildRouteValidation } from './utils/build_validation/route_validation'; export { transformError, buildSiemResponse } from './lib/detection_engine/routes/utils'; +export { readPrivileges } from './lib/detection_engine/privileges/read_privileges';