Skip to content

Commit

Permalink
[8.14] [Cases] Populate user info from fake requests (elastic#180671) (
Browse files Browse the repository at this point in the history
…elastic#181572)

# Backport

This will backport the following commits from `main` to `8.14`:
- [[Cases] Populate user info from fake requests
(elastic#180671)](elastic#180671)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Christos
Nasikas","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-04-24T13:38:24Z","message":"[Cases]
Populate user info from fake requests (elastic#180671)\n\n## Summary\r\n\r\nSet
a system user name when the request is fake. This is helpful to
show\r\nuser information to the case created by the case
action.\r\n\r\n## Testing\r\n\r\n1. Create a rule with a case
action\r\n2. In the created case verify that the `elastic/kibana` user
is shown\r\nand not the `Unknown` user\r\n\r\n<img width=\"2297\"
alt=\"Screenshot 2024-04-22 at 10 37
46 PM\"\r\nsrc=\"https://github.com/elastic/kibana/assets/7871006/abfcec4c-f2a4-4663-84e0-1816ada69167\">\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n\r\n### For
maintainers\r\n\r\n- [x] This was checked for breaking API changes and
was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"42fa118b7dd4e0ec9108ca056d5f705d6f5617e9","branchLabelMapping":{"^v8.15.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["bug","release_note:skip","Team:ResponseOps","Feature:Cases","v8.14.0","v8.15.0"],"title":"[Cases]
Populate user info from fake
requests","number":180671,"url":"https://github.com/elastic/kibana/pull/180671","mergeCommit":{"message":"[Cases]
Populate user info from fake requests (elastic#180671)\n\n## Summary\r\n\r\nSet
a system user name when the request is fake. This is helpful to
show\r\nuser information to the case created by the case
action.\r\n\r\n## Testing\r\n\r\n1. Create a rule with a case
action\r\n2. In the created case verify that the `elastic/kibana` user
is shown\r\nand not the `Unknown` user\r\n\r\n<img width=\"2297\"
alt=\"Screenshot 2024-04-22 at 10 37
46 PM\"\r\nsrc=\"https://github.com/elastic/kibana/assets/7871006/abfcec4c-f2a4-4663-84e0-1816ada69167\">\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n\r\n### For
maintainers\r\n\r\n- [x] This was checked for breaking API changes and
was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"42fa118b7dd4e0ec9108ca056d5f705d6f5617e9"}},"sourceBranch":"main","suggestedTargetBranches":["8.14"],"targetPullRequestStates":[{"branch":"8.14","label":"v8.14.0","branchLabelMappingKey":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.15.0","branchLabelMappingKey":"^v8.15.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/180671","number":180671,"mergeCommit":{"message":"[Cases]
Populate user info from fake requests (elastic#180671)\n\n## Summary\r\n\r\nSet
a system user name when the request is fake. This is helpful to
show\r\nuser information to the case created by the case
action.\r\n\r\n## Testing\r\n\r\n1. Create a rule with a case
action\r\n2. In the created case verify that the `elastic/kibana` user
is shown\r\nand not the `Unknown` user\r\n\r\n<img width=\"2297\"
alt=\"Screenshot 2024-04-22 at 10 37
46 PM\"\r\nsrc=\"https://github.com/elastic/kibana/assets/7871006/abfcec4c-f2a4-4663-84e0-1816ada69167\">\r\n\r\n\r\n###
Checklist\r\n\r\nDelete any items that are not applicable to this
PR.\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common scenarios\r\n\r\n### For
maintainers\r\n\r\n- [x] This was checked for breaking API changes and
was
[labeled\r\nappropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)\r\n\r\n---------\r\n\r\nCo-authored-by:
kibanamachine
<[email protected]>","sha":"42fa118b7dd4e0ec9108ca056d5f705d6f5617e9"}}]}]
BACKPORT-->

Co-authored-by: Christos Nasikas <[email protected]>
  • Loading branch information
kibanamachine and cnasikas authored Apr 24, 2024
1 parent 65cf0de commit e98ed18
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import type { PublicMethodsOf } from '@kbn/utility-types';
import { ActionsClient } from './actions_client';
import type { ActionsClient } from './actions_client';

type ActionsClientContract = PublicMethodsOf<ActionsClient>;
export type ActionsClientMock = jest.Mocked<ActionsClientContract>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import type { PublicMethodsOf } from '@kbn/utility-types';
import { ActionsAuthorization } from './actions_authorization';
import type { ActionsAuthorization } from './actions_authorization';

export type ActionsAuthorizationMock = jest.Mocked<PublicMethodsOf<ActionsAuthorization>>;

Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/actions/server/feature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* 2.0.
*/

import { DEFAULT_APP_CATEGORIES } from '@kbn/core-application-common';
import { i18n } from '@kbn/i18n';
import { DEFAULT_APP_CATEGORIES } from '@kbn/core/server';
import {
ACTION_SAVED_OBJECT_TYPE,
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/actions/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
"@kbn/actions-types",
"@kbn/core-http-server",
"@kbn/core-test-helpers-kbn-server",
"@kbn/security-plugin-types-server"
"@kbn/security-plugin-types-server",
"@kbn/core-application-common"
],
"exclude": [
"target/**/*",
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/cases/common/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ export const GET_CONNECTORS_CONFIGURE_API_TAG = 'casesGetConnectorsConfigure';
export const DEFAULT_USER_SIZE = 10;
export const MAX_ASSIGNEES_PER_CASE = 10;
export const NO_ASSIGNEES_FILTERING_KEYWORD = 'none';
export const KIBANA_SYSTEM_USERNAME = 'elastic/kibana';

/**
* Delays
Expand Down
124 changes: 124 additions & 0 deletions x-pack/plugins/cases/server/client/factory.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { coreMock, httpServerMock, loggingSystemMock } from '@kbn/core/server/mocks';
import { CasesClientFactory } from './factory';
import { createCasesClientFactoryMockArgs } from './mocks';
import { createCasesClient } from './client';
import type { FakeRawRequest } from '@kbn/core-http-server';
import { CoreKibanaRequest } from '@kbn/core-http-router-server-internal';

jest.mock('./client');

describe('CasesClientFactory', () => {
const coreStart = coreMock.createStart();
const request = httpServerMock.createKibanaRequest();

const rawRequest: FakeRawRequest = {
headers: {},
path: '/',
};

const fakeRequest = CoreKibanaRequest.from(rawRequest);
const createCasesClientMocked = createCasesClient as jest.Mock;
const logger = loggingSystemMock.createLogger();
const args = createCasesClientFactoryMockArgs();
let casesClientFactory: CasesClientFactory;

args.featuresPluginStart.getKibanaFeatures.mockReturnValue([]);

beforeEach(() => {
casesClientFactory = new CasesClientFactory(logger);
casesClientFactory.initialize(args);
jest.clearAllMocks();
});

describe('user info', () => {
it('constructs the user info from user profiles', async () => {
const scopedClusterClient = coreStart.elasticsearch.client.asScoped(request).asCurrentUser;
args.securityPluginStart.userProfiles.getCurrent.mockResolvedValueOnce({
// @ts-expect-error: not all fields are needed
user: { username: 'my_user', full_name: 'My user', email: '[email protected]' },
});

await casesClientFactory.create({
request,
savedObjectsService: coreStart.savedObjects,
scopedClusterClient,
});

expect(args.securityPluginStart.userProfiles.getCurrent).toHaveBeenCalled();
expect(args.securityPluginStart.authc.getCurrentUser).not.toHaveBeenCalled();
expect(createCasesClientMocked.mock.calls[0][0].user).toEqual({
username: 'my_user',
full_name: 'My user',
email: '[email protected]',
});
});

it('constructs the user info from the authc service if the user profile is not available', async () => {
const scopedClusterClient = coreStart.elasticsearch.client.asScoped(request).asCurrentUser;
// @ts-expect-error: not all fields are needed
args.securityPluginStart.authc.getCurrentUser.mockReturnValueOnce({
username: 'my_user_2',
full_name: 'My user 2',
email: '[email protected]',
});

await casesClientFactory.create({
request,
savedObjectsService: coreStart.savedObjects,
scopedClusterClient,
});

expect(args.securityPluginStart.userProfiles.getCurrent).toHaveBeenCalled();
expect(args.securityPluginStart.authc.getCurrentUser).toHaveBeenCalled();
expect(createCasesClientMocked.mock.calls[0][0].user).toEqual({
username: 'my_user_2',
full_name: 'My user 2',
email: '[email protected]',
});
});

it('constructs the user info from fake requests correctly', async () => {
const scopedClusterClient =
coreStart.elasticsearch.client.asScoped(fakeRequest).asCurrentUser;

await casesClientFactory.create({
request: fakeRequest,
savedObjectsService: coreStart.savedObjects,
scopedClusterClient,
});

expect(args.securityPluginStart.userProfiles.getCurrent).toHaveBeenCalled();
expect(args.securityPluginStart.authc.getCurrentUser).toHaveBeenCalled();
expect(createCasesClientMocked.mock.calls[0][0].user).toEqual({
username: 'elastic/kibana',
full_name: null,
email: null,
});
});

it('return null for all user fields if it cannot find the user info', async () => {
const scopedClusterClient = coreStart.elasticsearch.client.asScoped(request).asCurrentUser;

await casesClientFactory.create({
request,
savedObjectsService: coreStart.savedObjects,
scopedClusterClient,
});

expect(args.securityPluginStart.userProfiles.getCurrent).toHaveBeenCalled();
expect(args.securityPluginStart.authc.getCurrentUser).toHaveBeenCalled();
expect(createCasesClientMocked.mock.calls[0][0].user).toEqual({
username: null,
full_name: null,
email: null,
});
});
});
});
10 changes: 9 additions & 1 deletion x-pack/plugins/cases/server/client/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import type {
import type { PublicMethodsOf } from '@kbn/utility-types';
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
import type { FilesStart } from '@kbn/files-plugin/server';
import { SAVED_OBJECT_TYPES } from '../../common/constants';
import { KIBANA_SYSTEM_USERNAME, SAVED_OBJECT_TYPES } from '../../common/constants';
import { Authorization } from '../authorization/authorization';
import {
CaseConfigureService,
Expand Down Expand Up @@ -286,6 +286,14 @@ export class CasesClientFactory {
this.logger.debug(`Failed to retrieve user info from authc: ${error}`);
}

if (request.isFakeRequest) {
return {
username: KIBANA_SYSTEM_USERNAME,
full_name: null,
email: null,
};
}

return {
username: null,
full_name: null,
Expand Down
36 changes: 34 additions & 2 deletions x-pack/plugins/cases/server/client/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,20 @@ import type { PublicContract, PublicMethodsOf } from '@kbn/utility-types';
import { loggingSystemMock, savedObjectsClientMock } from '@kbn/core/server/mocks';
import type { ISavedObjectsSerializer } from '@kbn/core-saved-objects-server';

import { createFileServiceMock } from '@kbn/files-plugin/server/mocks';
import {
createFileServiceFactoryMock,
createFileServiceMock,
} from '@kbn/files-plugin/server/mocks';
import { securityMock } from '@kbn/security-plugin/server/mocks';
import { actionsClientMock } from '@kbn/actions-plugin/server/actions_client/actions_client.mock';
import { makeLensEmbeddableFactory } from '@kbn/lens-plugin/server/embeddable/make_lens_embeddable_factory';
import { serializerMock } from '@kbn/core-saved-objects-base-server-mocks';

import { spacesMock } from '@kbn/spaces-plugin/server/mocks';
import { featuresPluginMock } from '@kbn/features-plugin/server/mocks';
import { actionsMock } from '@kbn/actions-plugin/server/mocks';
import { notificationsMock } from '@kbn/notifications-plugin/server/mocks';
import { licensingMock } from '@kbn/licensing-plugin/server/mocks';
import { alertsMock } from '@kbn/alerting-plugin/server/mocks';
import type { CasesSearchRequest } from '../../common/types/api';
import type { CasesClient, CasesClientInternal } from '.';
import type { AttachmentsSubClient } from './attachments/client';
Expand Down Expand Up @@ -214,6 +222,30 @@ export const createCasesClientMockArgs = () => {
};
};

export const createCasesClientFactoryMockArgs = () => {
return {
securityPluginSetup: securityMock.createSetup(),
securityPluginStart: securityMock.createStart(),
spacesPluginStart: spacesMock.createStart(),
featuresPluginStart: featuresPluginMock.createSetup(),
actionsPluginStart: actionsMock.createStart(),
licensingPluginStart: licensingMock.createStart(),
notifications: notificationsMock.createStart(),
ruleRegistry: { getRacClientWithRequest: jest.fn(), alerting: alertsMock.createStart() },
filesPluginStart: { fileServiceFactory: createFileServiceFactoryMock() },
publicBaseUrl: 'https//example.com',
lensEmbeddableFactory: jest.fn().mockReturnValue(
makeLensEmbeddableFactory(
() => ({}),
() => ({}),
{}
)
),
externalReferenceAttachmentTypeRegistry: createExternalReferenceAttachmentTypeRegistryMock(),
persistableStateAttachmentTypeRegistry: createPersistableStateAttachmentTypeRegistryMock(),
};
};

export const createCasesClientMockSearchRequest = (
overwrites?: CasesSearchRequest
): CasesSearchRequest => ({
Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/cases/server/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { coreMock } from '@kbn/core/server/mocks';
import { usageCollectionPluginMock } from '@kbn/usage-collection-plugin/server/mocks';
import { licensingMock } from '@kbn/licensing-plugin/server/mocks';
import { featuresPluginMock } from '@kbn/features-plugin/server/mocks';
import { createFilesSetupMock } from '@kbn/files-plugin/server/mocks';
import { createFileServiceFactoryMock, createFilesSetupMock } from '@kbn/files-plugin/server/mocks';
import { securityMock } from '@kbn/security-plugin/server/mocks';
import { makeLensEmbeddableFactory } from '@kbn/lens-plugin/server/embeddable/make_lens_embeddable_factory';
import { taskManagerMock } from '@kbn/task-manager-plugin/server/mocks';
Expand Down Expand Up @@ -69,7 +69,7 @@ describe('Cases Plugin', () => {
pluginsStart = {
licensing: licensingMock.createStart(),
actions: actionsMock.createStart(),
files: { fileServiceFactory: { asScoped: jest.fn(), asInternal: jest.fn() } },
files: { fileServiceFactory: createFileServiceFactoryMock() },
features: featuresPluginMock.createStart(),
security: securityMock.createStart(),
notifications: notificationsMock.createStart(),
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/cases/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"@kbn/core-logging-server-mocks",
"@kbn/core-logging-browser-mocks",
"@kbn/data-views-plugin",
"@kbn/core-http-router-server-internal",
],
"exclude": [
"target/**/*",
Expand Down

0 comments on commit e98ed18

Please sign in to comment.