[Security Solution][Detection Engine] adds bulkGetUserProfiles privilege to Security Feature (#211824)

## Summary

- addresses https://github.com/elastic/kibana/issues/202051

Few observations, based on ticket
[description](https://github.com/elastic/kibana/issues/202051):

1. User can update assignees in alert(i.e. update any alert details,
which is handled by **SecuritySolution** priv)
2. User can see suggested users in searchbox
3. User **can not** see assignees details(name, avatar) in alerts table
column and alerts flyout(that's where error toast originates from)

Why this happens?
2 different APIs used to show users in searchbox and user details in
alerts table column:

1. API to show users in searchbox:
[/internal/detection_engine/users/_find](https://github.com/elastic/kibana/blob/8.18/x-pack/solutions/security/plugins/security_solution/server/lib/detection_engine/routes/users/suggest_user_profiles_route.ts#L24)
It requires `securitySolution` privilege
2. API for alerts table cell:
[/internal/security/user_profile/_bulk_get](https://github.com/elastic/kibana/blob/8.18/x-pack/platform/plugins/shared/security/server/routes/user_profile/bulk_get.ts#L20)
It requires `bulkGetUserProfiles` privilege

User was configured with read only Security Feature, that covers only
first API, that's why we see error
> API [POST /internal/security/user_profile/_bulk_get] is unauthorized
for user, this action is granted by the Kibana privileges
[bulkGetUserProfiles] (403)

However `bulkGetUserProfiles` is covered by `Cases` feature already. If
Cases access will be set to read, user would be able to see assignees
details through `/internal/security/user_profile/_bulk_get` API.
It happens, because cases API tags include `bulkGetUserProfiles`
privilege:
https://github.com/elastic/kibana/blob/8.18/x-pack/platform/plugins/shared/cases/common/utils/api_tags.ts#L32,
https://github.com/elastic/kibana/blob/8.18/x-pack/solutions/security/packages/features/src/cases/types.ts#L7

This PR includes `bulkGetUserProfiles` privilege in Security Feature:
https://github.com/elastic/kibana/pull/211824. Since, it's already
present in Cases feature, and user profiles available through Security
Solution `/internal/detection_engine/users/_find` API
This commit is contained in:
Vitalii Dmyterko 2025-03-04 15:08:41 +00:00 committed by GitHub
parent 601e4de6b8
commit 847be917a6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 51 additions and 7 deletions

View file

@ -118,6 +118,7 @@ export const getSecurityBaseKibanaFeature = ({
'timeline_read',
'notes_write',
'notes_read',
'bulkGetUserProfiles',
],
savedObject: {
all: ['alert', ...savedObjects],
@ -159,6 +160,7 @@ export const getSecurityBaseKibanaFeature = ({
'cloud-defend-read',
'timeline_read',
'notes_read',
'bulkGetUserProfiles',
],
savedObject: {
all: [],

View file

@ -87,6 +87,7 @@ export const getSecurityV2BaseKibanaFeature = ({
'cloud-security-posture-read',
'cloud-defend-all',
'cloud-defend-read',
'bulkGetUserProfiles',
],
savedObject: {
all: ['alert', ...savedObjects],
@ -104,7 +105,14 @@ export const getSecurityV2BaseKibanaFeature = ({
read: {
app: [APP_ID, CLOUD_POSTURE_APP_ID, CLOUD_DEFEND_APP_ID, 'kibana'],
catalogue: [APP_ID],
api: [APP_ID, 'lists-read', 'rac', 'cloud-security-posture-read', 'cloud-defend-read'],
api: [
APP_ID,
'lists-read',
'rac',
'cloud-security-posture-read',
'cloud-defend-read',
'bulkGetUserProfiles',
],
savedObject: {
all: [],
read: [...savedObjects],

View file

@ -21,9 +21,10 @@ import {
casesReadUser,
obsCasesAllUser,
obsCasesReadUser,
secAllCasesNoneUser,
secAllUser,
secReadCasesReadUser,
secAllCasesNoneUser,
secNoneUser,
} from './common/users';
export default ({ getService }: FtrProviderContext): void => {
@ -67,6 +68,7 @@ export default ({ getService }: FtrProviderContext): void => {
{ user: secReadCasesReadUser },
{ user: casesReadUser },
{ user: obsCasesReadUser },
{ user: secAllCasesNoneUser },
]) {
it(`User ${
user.username
@ -82,7 +84,7 @@ export default ({ getService }: FtrProviderContext): void => {
});
}
for (const { user } of [{ user: secAllCasesNoneUser }]) {
for (const { user } of [{ user: secNoneUser }]) {
it(`User ${
user.username
} with roles(s) ${user.roles.join()} cannot bulk get user profiles because they lack the bulkGetUserProfiles privilege`, async () => {

View file

@ -384,6 +384,30 @@ export const secReadCasesNone: Role = {
},
};
export const secNone: Role = {
name: 'sec_none_role_api_int',
privileges: {
elasticsearch: {
indices: [
{
names: ['*'],
privileges: ['all'],
},
],
},
kibana: [
{
feature: {
siem: [],
actions: ['all'],
actionsSimulators: ['all'],
},
spaces: ['*'],
},
],
},
};
/**
* Roles for Cases in the stack
*/

View file

@ -36,6 +36,7 @@ import {
secReadCasesAll,
secReadCasesNone,
secReadCasesRead,
secNone,
casesV2NoReopenWithCreateComment,
obsCasesV2NoReopenWithCreateComment,
secCasesV2NoReopenWithCreateComment,
@ -132,6 +133,12 @@ export const secReadUser: User = {
roles: [secRead.name],
};
export const secNoneUser: User = {
username: 'sec_none_user_api_int',
password: 'password',
roles: [secNone.name],
};
export const secReadCasesNoneUser: User = {
username: 'sec_read_cases_none_user_api_int',
password: 'password',
@ -297,6 +304,7 @@ export const users = [
secReadCasesAllUser,
secReadCasesReadUser,
secReadUser,
secNoneUser,
secReadCasesNoneUser,
casesOnlyDeleteUser,
casesOnlyReadDeleteUser,

View file

@ -229,6 +229,7 @@ export default function ({ getService }: FtrProviderContext) {
"api:cloud-security-posture-read",
"api:cloud-defend-all",
"api:cloud-defend-read",
"api:bulkGetUserProfiles",
"api:securitySolution-entity-analytics",
"api:securitySolution-threat-intelligence",
"api:securitySolution-showEndpointExceptions",
@ -839,7 +840,6 @@ export default function ({ getService }: FtrProviderContext) {
"ui:discover_v2/createShortUrl",
"ui:discover_v2/storeSearchSession",
"ui:discover_v2/generateCsv",
"api:bulkGetUserProfiles",
"api:dashboardUsageStats",
"api:downloadCsv",
"app:dashboards",
@ -1071,6 +1071,7 @@ export default function ({ getService }: FtrProviderContext) {
"api:cloud-security-posture-read",
"api:cloud-defend-all",
"api:cloud-defend-read",
"api:bulkGetUserProfiles",
"api:securitySolution-entity-analytics",
"api:securitySolution-threat-intelligence",
"app:securitySolution",
@ -1677,7 +1678,6 @@ export default function ({ getService }: FtrProviderContext) {
"ui:discover_v2/createShortUrl",
"ui:discover_v2/storeSearchSession",
"ui:discover_v2/generateCsv",
"api:bulkGetUserProfiles",
"api:dashboardUsageStats",
"api:downloadCsv",
"app:dashboards",
@ -1771,6 +1771,7 @@ export default function ({ getService }: FtrProviderContext) {
"api:rac",
"api:cloud-security-posture-read",
"api:cloud-defend-read",
"api:bulkGetUserProfiles",
"api:securitySolution-entity-analytics",
"api:securitySolution-threat-intelligence",
"app:securitySolution",
@ -2045,7 +2046,6 @@ export default function ({ getService }: FtrProviderContext) {
"saved_object:search/close_point_in_time",
"ui:discover_v2/show",
"ui:discover_v2/createShortUrl",
"api:bulkGetUserProfiles",
"api:dashboardUsageStats",
"app:dashboards",
"ui:catalogue/dashboard",
@ -2135,6 +2135,7 @@ export default function ({ getService }: FtrProviderContext) {
"api:rac",
"api:cloud-security-posture-read",
"api:cloud-defend-read",
"api:bulkGetUserProfiles",
"api:securitySolution-entity-analytics",
"api:securitySolution-threat-intelligence",
"api:securitySolution-showEndpointExceptions",
@ -2411,7 +2412,6 @@ export default function ({ getService }: FtrProviderContext) {
"saved_object:search/close_point_in_time",
"ui:discover_v2/show",
"ui:discover_v2/createShortUrl",
"api:bulkGetUserProfiles",
"api:dashboardUsageStats",
"app:dashboards",
"ui:catalogue/dashboard",