Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Cases] RBAC: Create & Find integration tests #95511

Merged
merged 19 commits into from
Apr 2, 2021
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion x-pack/plugins/cases/common/api/runtime_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ const getExcessProps = (props: rt.Props, r: Record<string, unknown>): string[] =
return ex;
};

export function excess<C extends rt.InterfaceType<rt.Props>>(codec: C): C {
export function excess<C extends rt.InterfaceType<rt.Props> | rt.PartialType<rt.Props>>(
codec: C
): C {
const r = new rt.InterfaceType(
codec.name,
codec.is,
Expand Down
5 changes: 4 additions & 1 deletion x-pack/plugins/cases/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ export const CASE_CONFIGURE_SAVED_OBJECT = 'cases-configure';
export const SAVED_OBJECT_TYPES = [
CASE_SAVED_OBJECT,
CASE_CONNECTOR_MAPPINGS_SAVED_OBJECT,
SUB_CASE_SAVED_OBJECT,
CASE_USER_ACTION_SAVED_OBJECT,
CASE_COMMENT_SAVED_OBJECT,
CASE_CONFIGURE_SAVED_OBJECT,
Expand Down Expand Up @@ -82,3 +81,7 @@ export const SECURITY_SOLUTION_OWNER = 'securitySolution';
* This flag governs enabling the case as a connector feature. It is disabled by default as the feature is not complete.
*/
export const ENABLE_CASE_CONNECTOR = false;

if (ENABLE_CASE_CONNECTOR) {
SAVED_OBJECT_TYPES.push(SUB_CASE_SAVED_OBJECT);
}
20 changes: 20 additions & 0 deletions x-pack/plugins/cases/server/authorization/mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* 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 type { PublicMethodsOf } from '@kbn/utility-types';
import { Authorization } from './authorization';

type Schema = PublicMethodsOf<Authorization>;
export type AuthorizationMock = jest.Mocked<Schema>;

export const createAuthorizationMock = () => {
const mocked: AuthorizationMock = {
ensureAuthorized: jest.fn(),
getFindAuthorizationFilter: jest.fn(),
};
return mocked;
};
3 changes: 2 additions & 1 deletion x-pack/plugins/cases/server/client/cases/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { pipe } from 'fp-ts/lib/pipeable';
import { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';

import type { PublicMethodsOf } from '@kbn/utility-types';
import { SavedObjectsClientContract, Logger } from 'src/core/server';
import { flattenCaseSavedObject, transformNewCase } from '../../routes/api/utils';

Expand Down Expand Up @@ -47,7 +48,7 @@ interface CreateCaseArgs {
userActionService: CaseUserActionServiceSetup;
theCase: CasePostRequest;
logger: Logger;
auth: Authorization;
auth: PublicMethodsOf<Authorization>;
}

/**
Expand Down
6 changes: 4 additions & 2 deletions x-pack/plugins/cases/server/client/cases/find.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ import { pipe } from 'fp-ts/lib/pipeable';
import { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';

import type { PublicMethodsOf } from '@kbn/utility-types';
import {
CasesFindResponse,
CasesFindRequest,
CasesFindRequestRt,
throwErrors,
caseStatuses,
CasesFindResponseRt,
excess,
} from '../../../common/api';

import { CASE_SAVED_OBJECT } from '../../../common/constants';
Expand All @@ -32,7 +34,7 @@ interface FindParams {
savedObjectsClient: SavedObjectsClientContract;
caseService: CaseServiceSetup;
logger: Logger;
auth: Authorization;
auth: PublicMethodsOf<Authorization>;
options: CasesFindRequest;
}

Expand All @@ -48,7 +50,7 @@ export const find = async ({
}: FindParams): Promise<CasesFindResponse> => {
try {
const queryParams = pipe(
CasesFindRequestRt.decode(options),
excess(CasesFindRequestRt).decode(options),
fold(throwErrors(Boom.badRequest), identity)
);

Expand Down
15 changes: 13 additions & 2 deletions x-pack/plugins/cases/server/client/cases/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
SavedObjectsFindResult,
Logger,
} from 'kibana/server';

import { nodeBuilder } from '../../../../../../src/plugins/data/common';
import {
flattenCaseSavedObject,
isCommentRequestTypeAlertOrGenAlert,
Expand Down Expand Up @@ -134,7 +136,13 @@ async function throwIfInvalidUpdateOfTypeWithAlerts({
options: {
fields: [],
// there should never be generated alerts attached to an individual case but we'll check anyway
filter: `${CASE_COMMENT_SAVED_OBJECT}.attributes.type: ${CommentType.alert} OR ${CASE_COMMENT_SAVED_OBJECT}.attributes.type: ${CommentType.generatedAlert}`,
filter: nodeBuilder.or([
nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert),
nodeBuilder.is(
`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`,
CommentType.generatedAlert
),
]),
page: 1,
perPage: 1,
},
Expand Down Expand Up @@ -191,7 +199,10 @@ async function getAlertComments({
id: idsOfCasesToSync,
includeSubCaseComments: true,
options: {
filter: `${CASE_COMMENT_SAVED_OBJECT}.attributes.type: ${CommentType.alert} OR ${CASE_COMMENT_SAVED_OBJECT}.attributes.type: ${CommentType.generatedAlert}`,
filter: nodeBuilder.or([
nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.alert),
nodeBuilder.is(`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`, CommentType.generatedAlert),
]),
},
});
}
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/cases/server/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import type { PublicMethodsOf } from '@kbn/utility-types';
import { ElasticsearchClient, SavedObjectsClientContract, Logger } from 'src/core/server';
import {
CasesClientConstructorArguments,
Expand Down Expand Up @@ -53,7 +54,7 @@ export class CasesClientHandler implements CasesClient {
private readonly _userActionService: CaseUserActionServiceSetup;
private readonly _alertsService: AlertServiceContract;
private readonly logger: Logger;
private readonly authorization: Authorization;
private readonly authorization: PublicMethodsOf<Authorization>;

constructor(clientArgs: CasesClientConstructorArguments) {
this._scopedClusterClient = clientArgs.scopedClusterClient;
Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/cases/server/client/comments/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';

import { SavedObject, SavedObjectsClientContract, Logger } from 'src/core/server';
import { nodeBuilder } from '../../../../../../src/plugins/data/common';
import { decodeCommentRequest, isCommentRequestTypeGenAlert } from '../../routes/api/utils';

import {
Expand Down Expand Up @@ -63,7 +64,10 @@ async function getSubCase({
id: mostRecentSubCase.id,
options: {
fields: [],
filter: `${CASE_COMMENT_SAVED_OBJECT}.attributes.type: ${CommentType.generatedAlert}`,
filter: nodeBuilder.is(
`${CASE_COMMENT_SAVED_OBJECT}.attributes.type`,
CommentType.generatedAlert
),
page: 1,
perPage: 1,
},
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/cases/server/client/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
createUserActionServiceMock,
createAlertServiceMock,
} from '../services/mocks';
import { createAuthorizationMock } from '../authorization/mock';

jest.mock('./client');
import { CasesClientHandler } from './client';
Expand All @@ -31,6 +32,7 @@ const caseService = createCaseServiceMock();
const connectorMappingsService = connectorMappingsServiceMock();
const savedObjectsClient = savedObjectsClientMock.create();
const userActionService = createUserActionServiceMock();
const authorization = createAuthorizationMock();

describe('createExternalCasesClient()', () => {
test('it creates the client correctly', async () => {
Expand All @@ -44,6 +46,7 @@ describe('createExternalCasesClient()', () => {
savedObjectsClient,
userActionService,
logger,
authorization,
});
expect(CasesClientHandler).toHaveBeenCalledTimes(1);
});
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/cases/server/client/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import type { PublicMethodsOf } from '@kbn/utility-types';
import { ElasticsearchClient, SavedObjectsClientContract, Logger } from 'kibana/server';
import { ActionsClient } from '../../../actions/server';
import {
Expand Down Expand Up @@ -78,7 +79,7 @@ export interface CasesClientConstructorArguments {
userActionService: CaseUserActionServiceSetup;
alertsService: AlertServiceContract;
logger: Logger;
authorization: Authorization;
authorization: PublicMethodsOf<Authorization>;
}

export interface ConfigureFields {
Expand Down
32 changes: 1 addition & 31 deletions x-pack/plugins/cases/server/common/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import { SavedObjectsFindResponse } from 'kibana/server';
import { AssociationType, CommentAttributes, CommentRequest, CommentType } from '../../common/api';
import { transformNewComment } from '../routes/api/utils';
import { combineFilters, countAlerts, countAlertsForID, groupTotalAlertsByID } from './utils';
import { countAlerts, countAlertsForID, groupTotalAlertsByID } from './utils';

interface CommentReference {
ids: string[];
Expand Down Expand Up @@ -47,36 +47,6 @@ function createCommentFindResponse(
}

describe('common utils', () => {
describe('combineFilters', () => {
it("creates a filter string with two values and'd together", () => {
expect(combineFilters(['a', 'b'], 'AND')).toBe('(a AND b)');
});

it('creates a filter string with three values or together', () => {
expect(combineFilters(['a', 'b', 'c'], 'OR')).toBe('(a OR b OR c)');
});

it('ignores empty strings', () => {
expect(combineFilters(['', 'a', '', 'b'], 'AND')).toBe('(a AND b)');
});

it('returns an empty string if all filters are empty strings', () => {
expect(combineFilters(['', ''], 'OR')).toBe('');
});

it('returns an empty string if the filters are undefined', () => {
expect(combineFilters(undefined, 'OR')).toBe('');
});

it('returns a value without parenthesis when only a single filter is provided', () => {
expect(combineFilters(['a'], 'OR')).toBe('a');
});

it('returns a string without parenthesis when only a single non empty filter is provided', () => {
expect(combineFilters(['', ''], 'AND')).toBe('');
});
});

describe('countAlerts', () => {
it('returns 0 when no alerts are found', () => {
expect(
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/cases/server/connectors/case/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,7 @@ describe('case connector', () => {
settings: {
syncAlerts: true,
},
scope: 'securitySolution',
};

mockCasesClient.create.mockReturnValue(Promise.resolve(createReturn));
Expand Down Expand Up @@ -1077,6 +1078,7 @@ describe('case connector', () => {
settings: {
syncAlerts: true,
},
scope: 'securitySolution',
},
];

Expand Down Expand Up @@ -1168,6 +1170,7 @@ describe('case connector', () => {
settings: {
syncAlerts: true,
},
scope: 'securitySolution',
};

mockCasesClient.addComment.mockReturnValue(Promise.resolve(commentReturn));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const mockCases: Array<SavedObject<ESCaseAttributes>> = [
settings: {
syncAlerts: true,
},
scope: 'securitySolution',
},
references: [],
updated_at: '2019-11-25T21:54:48.952Z',
Expand Down Expand Up @@ -96,6 +97,7 @@ export const mockCases: Array<SavedObject<ESCaseAttributes>> = [
settings: {
syncAlerts: true,
},
scope: 'securitySolution',
},
references: [],
updated_at: '2019-11-25T22:32:00.900Z',
Expand Down Expand Up @@ -138,6 +140,7 @@ export const mockCases: Array<SavedObject<ESCaseAttributes>> = [
settings: {
syncAlerts: true,
},
scope: 'securitySolution',
},
references: [],
updated_at: '2019-11-25T22:32:17.947Z',
Expand Down Expand Up @@ -184,6 +187,7 @@ export const mockCases: Array<SavedObject<ESCaseAttributes>> = [
settings: {
syncAlerts: true,
},
scope: 'securitySolution',
},
references: [],
updated_at: '2019-11-25T22:32:17.947Z',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export const newCase: CasePostRequest = {
settings: {
syncAlerts: true,
},
scope: 'securitySolution',
};

export const getActions = (): FindActionResult[] => [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { pipe } from 'fp-ts/lib/pipeable';
import { fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';

import { esKuery } from '../../../../../../../../src/plugins/data/server';
import {
AssociationType,
CommentsResponseRt,
Expand Down Expand Up @@ -63,6 +64,7 @@ export function initFindCaseCommentsApi({ caseService, router, logger }: RouteDe

const id = query.subCaseId ?? request.params.case_id;
const associationType = query.subCaseId ? AssociationType.subCase : AssociationType.case;
const { filter, ...queryWithoutFilter } = query;
const args = query
? {
caseService,
Expand All @@ -75,7 +77,8 @@ export function initFindCaseCommentsApi({ caseService, router, logger }: RouteDe
page: defaultPage,
perPage: defaultPerPage,
sortField: 'created_at',
...query,
filter: filter != null ? esKuery.fromKueryExpression(filter) : filter,
...queryWithoutFilter,
},
associationType,
}
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/cases/server/routes/api/cases/find_cases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function initFindCasesApi({ caseService, router, logger }: RouteDeps) {
return response.badRequest({ body: 'RouteHandlerContext is not registered for cases' });
}
const casesClient = await context.cases.getCasesClient();
const options = request.body as CasesFindRequest;
const options = request.query as CasesFindRequest;

return response.ok({
body: await casesClient.find({ ...options }),
Expand Down
Loading