Skip to content

Commit

Permalink
[Roles] Use Query Roles API for Role Management grid screen (#194630)
Browse files Browse the repository at this point in the history
Closes #186266

## Release notes

Enhanced Role management to manage larger number of roles by adding
server side filtering, pagination and querying.

## Summary
- Replaced the usage of Get Roles API with Query Role API
- Added server side pagination and filtering with a maximum limit of
10000 keys (default for max results on index). Added new label to
indicate that we show only 10k results.
- Search box replicates client side implementation by only filtering on
Role names.

### Run locally
Start ES ~with the JVM option to enable this feature~:
```
yarn es snapshot --license=trial
```
Start Kibana normally
```
yarn start --no-base-path
```

Navigate to Stack Management > Roles and verify the same behavior as the
screen recording below

### Screen recording


https://github.com/user-attachments/assets/a447e7df-8aa1-4044-a6b2-0aafe56844a9



## Technical notes
- Client side EuiInMemory table has been replaced by EuiSearchBar,
EuiBasicTable and Filters
- One new Kibana endpoint added
    -  `roles/_query` 
- Replicates existing get_role endpoint by being public and added to
Open API spec
- Extra logic to handle previously UI only filter to show/hide reserved
roles
- Parse the query to construct the correct DSL if the filter is present
- Update Get All Roles by Space internal API to use the Query Role and
filter by space id using query DSL.

### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [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

---------

Co-authored-by: Elastic Machine <[email protected]>
Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
3 people authored Jan 29, 2025
1 parent 4da814d commit 66dab0a
Show file tree
Hide file tree
Showing 21 changed files with 1,374 additions and 478 deletions.
74 changes: 74 additions & 0 deletions oas_docs/bundle.json
Original file line number Diff line number Diff line change
Expand Up @@ -40769,6 +40769,80 @@
]
}
},
"/api/security/role/_query": {
"post": {
"operationId": "post-security-role-query",
"parameters": [
{
"description": "A required header to protect against CSRF attacks",
"in": "header",
"name": "kbn-xsrf",
"required": true,
"schema": {
"example": "true",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"filters": {
"additionalProperties": false,
"properties": {
"showReservedRoles": {
"type": "boolean"
}
},
"type": "object"
},
"from": {
"type": "number"
},
"query": {
"type": "string"
},
"size": {
"type": "number"
},
"sort": {
"additionalProperties": false,
"properties": {
"direction": {
"enum": [
"asc",
"desc"
],
"type": "string"
},
"field": {
"type": "string"
}
},
"required": [
"field",
"direction"
],
"type": "object"
}
},
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Indicates a successful call."
}
},
"summary": "Query roles",
"tags": []
}
},
"/api/security/role/{name}": {
"delete": {
"operationId": "delete-security-role-name",
Expand Down
74 changes: 74 additions & 0 deletions oas_docs/bundle.serverless.json
Original file line number Diff line number Diff line change
Expand Up @@ -40769,6 +40769,80 @@
]
}
},
"/api/security/role/_query": {
"post": {
"operationId": "post-security-role-query",
"parameters": [
{
"description": "A required header to protect against CSRF attacks",
"in": "header",
"name": "kbn-xsrf",
"required": true,
"schema": {
"example": "true",
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"additionalProperties": false,
"properties": {
"filters": {
"additionalProperties": false,
"properties": {
"showReservedRoles": {
"type": "boolean"
}
},
"type": "object"
},
"from": {
"type": "number"
},
"query": {
"type": "string"
},
"size": {
"type": "number"
},
"sort": {
"additionalProperties": false,
"properties": {
"direction": {
"enum": [
"asc",
"desc"
],
"type": "string"
},
"field": {
"type": "string"
}
},
"required": [
"field",
"direction"
],
"type": "object"
}
},
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Indicates a successful call."
}
},
"summary": "Query roles",
"tags": []
}
},
"/api/security/role/{name}": {
"delete": {
"operationId": "delete-security-role-name",
Expand Down
50 changes: 50 additions & 0 deletions oas_docs/output/kibana.serverless.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37827,6 +37827,56 @@ paths:
tags:
- roles
x-beta: true
/api/security/role/_query:
post:
operationId: post-security-role-query
parameters:
- description: A required header to protect against CSRF attacks
in: header
name: kbn-xsrf
required: true
schema:
example: 'true'
type: string
requestBody:
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
additionalProperties: false
type: object
properties:
filters:
additionalProperties: false
type: object
properties:
showReservedRoles:
type: boolean
from:
type: number
query:
type: string
size:
type: number
sort:
additionalProperties: false
type: object
properties:
direction:
enum:
- asc
- desc
type: string
field:
type: string
required:
- field
- direction
responses:
'200':
description: Indicates a successful call.
summary: Query roles
tags: []
x-beta: true
/api/security/role/{name}:
delete:
operationId: delete-security-role-name
Expand Down
49 changes: 49 additions & 0 deletions oas_docs/output/kibana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40299,6 +40299,55 @@ paths:
summary: Get all roles
tags:
- roles
/api/security/role/_query:
post:
operationId: post-security-role-query
parameters:
- description: A required header to protect against CSRF attacks
in: header
name: kbn-xsrf
required: true
schema:
example: 'true'
type: string
requestBody:
content:
application/json; Elastic-Api-Version=2023-10-31:
schema:
additionalProperties: false
type: object
properties:
filters:
additionalProperties: false
type: object
properties:
showReservedRoles:
type: boolean
from:
type: number
query:
type: string
size:
type: number
sort:
additionalProperties: false
type: object
properties:
direction:
enum:
- asc
- desc
type: string
field:
type: string
required:
- field
- direction
responses:
'200':
description: Indicates a successful call.
summary: Query roles
tags: []
/api/security/role/{name}:
delete:
operationId: delete-security-role-name
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export type {
AuthenticationProvider,
} from './src/authentication';
export type {
QueryRolesRole,
QueryRolesResult,
RemoteClusterPrivilege,
Role,
RoleIndexPrivilege,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
export type { FeaturesPrivileges } from './features_privileges';
export type { RawKibanaFeaturePrivileges, RawKibanaPrivileges } from './raw_kibana_privileges';
export type {
QueryRolesRole,
QueryRolesResult,
RemoteClusterPrivilege,
Role,
RoleKibanaPrivilege,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
* 2.0.
*/

import { estypes } from '@elastic/elasticsearch';

import type { FeaturesPrivileges } from './features_privileges';

export interface RoleIndexPrivilege {
Expand Down Expand Up @@ -55,3 +57,11 @@ export interface Role {
_transform_error?: string[];
_unrecognized_applications?: string[];
}

export type QueryRolesRole = estypes.SecurityQueryRoleQueryRole;

export interface QueryRolesResult {
roles: Role[];
count: number;
total: number;
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ export const rolesAPIClientMock = {
deleteRole: jest.fn(),
saveRole: jest.fn(),
bulkUpdateRoles: jest.fn(),
queryRoles: jest.fn(),
}),
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,26 @@
* 2.0.
*/

import type { Criteria } from '@elastic/eui';

import type { HttpStart } from '@kbn/core/public';
import type { QueryRolesResult } from '@kbn/security-plugin-types-common';
import type { BulkUpdatePayload, BulkUpdateRoleResponse } from '@kbn/security-plugin-types-public';

import type { Role, RoleIndexPrivilege, RoleRemoteIndexPrivilege } from '../../../common';
import { API_VERSIONS } from '../../../common/constants';
import { copyRole } from '../../../common/model';

export interface QueryRoleParams {
query: string;
from: number;
size: number;
filters?: {
showReservedRoles?: boolean;
};
sort: Criteria<Role>['sort'];
}

const version = API_VERSIONS.roles.public.v1;

export class RolesAPIClient {
Expand All @@ -24,6 +37,13 @@ export class RolesAPIClient {
});
};

public queryRoles = async (params?: QueryRoleParams) => {
return await this.http.post<QueryRolesResult>(`/api/security/role/_query`, {
version,
body: JSON.stringify(params || {}),
});
};

public getRole = async (roleName: string) => {
return await this.http.get<Role>(`/api/security/role/${encodeURIComponent(roleName)}`, {
version,
Expand Down
Loading

0 comments on commit 66dab0a

Please sign in to comment.