Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
f258504
Move routes one level up
cnasikas Apr 15, 2021
60ece3a
Improve clients signatures
cnasikas Apr 15, 2021
acb83b2
Add authorization to get all tags route
cnasikas Apr 15, 2021
bcec894
Add owner filter to all tags route
cnasikas Apr 19, 2021
81cb517
Add authorization to get all reporters route
cnasikas Apr 19, 2021
aebc4da
Add authorization to get get route
cnasikas Apr 19, 2021
254f84c
Add authorization to create configuration route
cnasikas Apr 20, 2021
c67d8e5
Remove *asUser util functions
cnasikas Apr 20, 2021
8095962
Merge branch 'cases-rbac-poc' into auth_cases_routes
cnasikas Apr 20, 2021
4e71fd4
Add filter operation to tags & reporters
cnasikas Apr 20, 2021
87c353b
Switch to the new utils functions
cnasikas Apr 20, 2021
872e1bd
Create combineAuthorizedAndOwnerFilter util function
cnasikas Apr 20, 2021
eb941c7
Add authorization to configurations route
cnasikas Apr 21, 2021
f2b3f07
Fix tests
cnasikas Apr 22, 2021
194bbdb
Add authorization to delete configuration route
cnasikas Apr 23, 2021
0c1ca8b
Remove unecessary send from get calls
cnasikas Apr 23, 2021
0202914
Change doc type
cnasikas Apr 23, 2021
6affd79
Remove await from inside Promise.all
cnasikas Apr 23, 2021
7cb3b76
Refactor to use excess for owner
cnasikas Apr 23, 2021
dbbc2f3
Throw if there is no mapping
cnasikas Apr 23, 2021
157e834
Fix types
cnasikas Apr 23, 2021
4d6fbe7
ensureSavedObjectsAreAuthorized for getTags & getReporters
cnasikas Apr 23, 2021
85fbd91
Fix errors
cnasikas Apr 23, 2021
1b70247
PR feedback
cnasikas Apr 26, 2021
3f6fafc
Fix types
cnasikas Apr 26, 2021
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
9 changes: 9 additions & 0 deletions x-pack/plugins/cases/common/api/cases/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,12 @@ export const ExternalServiceResponseRt = rt.intersection([
}),
]);

export const AllTagsFindRequestRt = rt.partial({
owner: rt.union([rt.array(rt.string), rt.string]),
});

export const AllReportersFindRequestRt = AllTagsFindRequestRt;

export type CaseAttributes = rt.TypeOf<typeof CaseAttributesRt>;
/**
* This field differs from the CasePostRequest in that the post request's type field can be optional. This type requires
Expand All @@ -198,3 +204,6 @@ export type ESCaseAttributes = Omit<CaseAttributes, 'connector'> & { connector:
export type ESCasePatchRequest = Omit<CasePatchRequest, 'connector'> & {
connector?: ESCaseConnector;
};

export type AllTagsFindRequest = rt.TypeOf<typeof AllTagsFindRequestRt>;
export type AllReportersFindRequest = AllTagsFindRequest;
21 changes: 20 additions & 1 deletion x-pack/plugins/cases/common/api/cases/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,22 @@ import * as rt from 'io-ts';

import { UserRT } from '../user';
import { CaseConnectorRt, ConnectorMappingsRt, ESCaseConnector } from '../connectors';
import { OmitProp } from '../runtime_types';

// TODO: we will need to add this type rt.literal('close-by-third-party')
const ClosureTypeRT = rt.union([rt.literal('close-by-user'), rt.literal('close-by-pushing')]);

const CasesConfigureBasicRt = rt.type({
connector: CaseConnectorRt,
closure_type: ClosureTypeRT,
owner: rt.string,
});

const CasesConfigureBasicWithoutOwnerRt = rt.type(OmitProp(CasesConfigureBasicRt.props, 'owner'));

export const CasesConfigureRequestRt = CasesConfigureBasicRt;
export const CasesConfigurePatchRt = rt.intersection([
rt.partial(CasesConfigureBasicRt.props),
rt.partial(CasesConfigureBasicWithoutOwnerRt.props),
rt.type({ version: rt.string }),
]);

Expand All @@ -38,18 +42,33 @@ export const CaseConfigureResponseRt = rt.intersection([
CaseConfigureAttributesRt,
ConnectorMappingsRt,
rt.type({
id: rt.string,
version: rt.string,
error: rt.union([rt.string, rt.null]),
owner: rt.string,
}),
]);

export const GetConfigureFindRequestRt = rt.partial({
owner: rt.union([rt.array(rt.string), rt.string]),
});

export const CaseConfigureRequestParamsRt = rt.type({
configuration_id: rt.string,
});

export const CaseConfigurationsResponseRt = rt.array(CaseConfigureResponseRt);

export type ClosureType = rt.TypeOf<typeof ClosureTypeRT>;
export type CasesConfigure = rt.TypeOf<typeof CasesConfigureBasicRt>;
export type CasesConfigureRequest = rt.TypeOf<typeof CasesConfigureRequestRt>;
export type CasesConfigurePatch = rt.TypeOf<typeof CasesConfigurePatchRt>;
export type CasesConfigureAttributes = rt.TypeOf<typeof CaseConfigureAttributesRt>;
export type CasesConfigureResponse = rt.TypeOf<typeof CaseConfigureResponseRt>;
export type CasesConfigurationsResponse = rt.TypeOf<typeof CaseConfigurationsResponseRt>;

export type ESCasesConfigureAttributes = Omit<CasesConfigureAttributes, 'connector'> & {
connector: ESCaseConnector;
};

export type GetConfigureFindRequest = rt.TypeOf<typeof GetConfigureFindRequestRt>;
1 change: 1 addition & 0 deletions x-pack/plugins/cases/common/api/connectors/mappings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const ConnectorMappingsAttributesRT = rt.type({

export const ConnectorMappingsRt = rt.type({
mappings: rt.array(ConnectorMappingsAttributesRT),
owner: rt.string,
});

export type ConnectorMappingsAttributes = rt.TypeOf<typeof ConnectorMappingsAttributesRT>;
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/cases/common/api/runtime_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { omit } from 'lodash';
import { either, fold } from 'fp-ts/lib/Either';
import { identity } from 'fp-ts/lib/function';
import { pipe } from 'fp-ts/lib/pipeable';
Expand All @@ -13,6 +14,9 @@ import { isObject } from 'lodash/fp';

type ErrorFactory = (message: string) => Error;

export const OmitProp = <O extends rt.Props, K extends keyof O>(o: O, k: K): Omit<O, K> =>
omit(o, k);

export const formatErrors = (errors: rt.Errors): string[] => {
const err = errors.map((error) => {
if (error.message != null) {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/cases/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const SAVED_OBJECT_TYPES = [
export const CASES_URL = '/api/cases';
export const CASE_DETAILS_URL = `${CASES_URL}/{case_id}`;
export const CASE_CONFIGURE_URL = `${CASES_URL}/configure`;
export const CASE_CONFIGURE_DETAILS_URL = `${CASES_URL}/configure/{configuration_id}`;
export const CASE_CONFIGURE_CONNECTORS_URL = `${CASE_CONFIGURE_URL}/connectors`;

export const SUB_CASES_PATCH_DEL_URL = `${CASES_URL}/sub_cases`;
Expand Down
42 changes: 41 additions & 1 deletion x-pack/plugins/cases/server/authorization/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { EventType } from '../../../security/server';
import { CASE_SAVED_OBJECT } from '../../common/constants';
import { CASE_CONFIGURE_SAVED_OBJECT, CASE_SAVED_OBJECT } from '../../common/constants';
import { Verbs, ReadOperations, WriteOperations, OperationDetails } from './types';

export * from './authorization';
Expand Down Expand Up @@ -66,6 +66,22 @@ export const Operations: Record<ReadOperations | WriteOperations, OperationDetai
docType: 'case',
savedObjectType: CASE_SAVED_OBJECT,
},
[WriteOperations.CreateConfiguration]: {
type: EventType.CREATION,
name: WriteOperations.CreateConfiguration,
action: 'create-configuration',
verbs: createVerbs,
docType: 'case configuration',
savedObjectType: CASE_CONFIGURE_SAVED_OBJECT,
},
[WriteOperations.UpdateConfiguration]: {
type: EventType.CHANGE,
name: WriteOperations.UpdateConfiguration,
action: 'update-configuration',
verbs: updateVerbs,
docType: 'case configuration',
savedObjectType: CASE_CONFIGURE_SAVED_OBJECT,
},
[ReadOperations.GetCase]: {
type: EventType.ACCESS,
name: ReadOperations.GetCase,
Expand All @@ -82,4 +98,28 @@ export const Operations: Record<ReadOperations | WriteOperations, OperationDetai
docType: 'cases',
savedObjectType: CASE_SAVED_OBJECT,
},
[ReadOperations.GetTags]: {
type: EventType.ACCESS,
name: ReadOperations.GetCase,
action: 'get-tags',
verbs: accessVerbs,
docType: 'case',
savedObjectType: CASE_SAVED_OBJECT,
},
[ReadOperations.GetReporters]: {
type: EventType.ACCESS,
name: ReadOperations.GetReporters,
action: 'get-reporters',
verbs: accessVerbs,
docType: 'case',
savedObjectType: CASE_SAVED_OBJECT,
},
[ReadOperations.FindConfigurations]: {
type: EventType.ACCESS,
name: ReadOperations.FindConfigurations,
action: 'find-configurations',
verbs: accessVerbs,
docType: 'case configurations',
savedObjectType: CASE_CONFIGURE_SAVED_OBJECT,
},
};
8 changes: 8 additions & 0 deletions x-pack/plugins/cases/server/authorization/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,24 @@ export type GetSpaceFn = (request: KibanaRequest) => Promise<Space | undefined>;

// TODO: we need to have an operation per entity route so I think we need to create a bunch like
// getCase, getComment, getSubCase etc for each, need to think of a clever way of creating them for all the routes easily?

// if you add a value here you'll likely also need to make changes here:
// x-pack/plugins/security/server/authorization/privileges/feature_privilege_builder/cases.ts
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💯

export enum ReadOperations {
GetCase = 'getCase',
FindCases = 'findCases',
GetTags = 'getTags',
GetReporters = 'getReporters',
FindConfigurations = 'findConfigurations',
}

// TODO: comments
export enum WriteOperations {
CreateCase = 'createCase',
DeleteCase = 'deleteCase',
UpdateCase = 'updateCase',
CreateConfiguration = 'createConfiguration',
UpdateConfiguration = 'updateConfiguration',
}

/**
Expand Down
20 changes: 3 additions & 17 deletions x-pack/plugins/cases/server/client/alerts/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,10 @@ export interface AlertSubClient {
updateStatus(args: AlertUpdateStatus): Promise<void>;
}

export const createAlertsSubClient = (args: CasesClientArgs): AlertSubClient => {
const { alertsService, scopedClusterClient, logger } = args;

export const createAlertsSubClient = (clientArgs: CasesClientArgs): AlertSubClient => {
const alertsSubClient: AlertSubClient = {
get: (params: AlertGet) =>
get({
...params,
alertsService,
scopedClusterClient,
logger,
}),
updateStatus: (params: AlertUpdateStatus) =>
updateStatus({
...params,
alertsService,
scopedClusterClient,
logger,
}),
get: (params: AlertGet) => get(params, clientArgs),
updateStatus: (params: AlertUpdateStatus) => updateStatus(params, clientArgs),
};

return Object.freeze(alertsSubClient);
Expand Down
17 changes: 6 additions & 11 deletions x-pack/plugins/cases/server/client/alerts/get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,19 @@
* 2.0.
*/

import { ElasticsearchClient, Logger } from 'kibana/server';
import { AlertInfo } from '../../common';
import { AlertServiceContract } from '../../services';
import { CasesClientGetAlertsResponse } from './types';
import { CasesClientArgs } from '..';

interface GetParams {
alertsService: AlertServiceContract;
alertsInfo: AlertInfo[];
scopedClusterClient: ElasticsearchClient;
logger: Logger;
}

export const get = async ({
alertsService,
alertsInfo,
scopedClusterClient,
logger,
}: GetParams): Promise<CasesClientGetAlertsResponse> => {
export const get = async (
{ alertsInfo }: GetParams,
clientArgs: CasesClientArgs
): Promise<CasesClientGetAlertsResponse> => {
const { alertsService, scopedClusterClient, logger } = clientArgs;
if (alertsInfo.length === 0) {
return [];
}
Expand Down
17 changes: 6 additions & 11 deletions x-pack/plugins/cases/server/client/alerts/update_status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,17 @@
* 2.0.
*/

import { ElasticsearchClient, Logger } from 'src/core/server';
import { AlertServiceContract } from '../../services';
import { UpdateAlertRequest } from './client';
import { CasesClientArgs } from '..';

interface UpdateAlertsStatusArgs {
alertsService: AlertServiceContract;
alerts: UpdateAlertRequest[];
scopedClusterClient: ElasticsearchClient;
logger: Logger;
}

export const updateStatus = async ({
alertsService,
alerts,
scopedClusterClient,
logger,
}: UpdateAlertsStatusArgs): Promise<void> => {
export const updateStatus = async (
{ alerts }: UpdateAlertsStatusArgs,
clientArgs: CasesClientArgs
): Promise<void> => {
const { alertsService, scopedClusterClient, logger } = clientArgs;
await alertsService.updateAlertsStatus({ alerts, scopedClusterClient, logger });
};
14 changes: 6 additions & 8 deletions x-pack/plugins/cases/server/client/attachments/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,15 +286,13 @@ async function getCombinedCase({
interface AddCommentArgs {
caseId: string;
comment: CommentRequest;
casesClientInternal: CasesClientInternal;
}

export const addComment = async ({
caseId,
comment,
casesClientInternal,
...rest
}: AddCommentArgs & CasesClientArgs): Promise<CaseResponse> => {
export const addComment = async (
{ caseId, comment }: AddCommentArgs,
clientArgs: CasesClientArgs,
casesClientInternal: CasesClientInternal
): Promise<CaseResponse> => {
const query = pipe(
CommentRequestRt.decode(comment),
fold(throwErrors(Boom.badRequest), identity)
Expand All @@ -307,7 +305,7 @@ export const addComment = async ({
attachmentService,
user,
logger,
} = rest;
} = clientArgs;

if (isCommentRequestTypeGenAlert(comment)) {
if (!ENABLE_CASE_CONNECTOR) {
Expand Down
24 changes: 9 additions & 15 deletions x-pack/plugins/cases/server/client/attachments/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ interface AttachmentsAdd {
}

export interface AttachmentsSubClient {
add(args: AttachmentsAdd): Promise<CaseResponse>;
add(params: AttachmentsAdd): Promise<CaseResponse>;
deleteAll(deleteAllArgs: DeleteAllArgs): Promise<void>;
delete(deleteArgs: DeleteArgs): Promise<void>;
find(findArgs: FindArgs): Promise<CommentsResponse>;
Expand All @@ -36,23 +36,17 @@ export interface AttachmentsSubClient {
}

export const createAttachmentsSubClient = (
args: CasesClientArgs,
clientArgs: CasesClientArgs,
casesClientInternal: CasesClientInternal
): AttachmentsSubClient => {
const attachmentSubClient: AttachmentsSubClient = {
add: ({ caseId, comment }: AttachmentsAdd) =>
addComment({
...args,
casesClientInternal,
caseId,
comment,
}),
deleteAll: (deleteAllArgs: DeleteAllArgs) => deleteAll(deleteAllArgs, args),
delete: (deleteArgs: DeleteArgs) => deleteComment(deleteArgs, args),
find: (findArgs: FindArgs) => find(findArgs, args),
getAll: (getAllArgs: GetAllArgs) => getAll(getAllArgs, args),
get: (getArgs: GetArgs) => get(getArgs, args),
update: (updateArgs: UpdateArgs) => update(updateArgs, args),
add: (params: AttachmentsAdd) => addComment(params, clientArgs, casesClientInternal),
deleteAll: (deleteAllArgs: DeleteAllArgs) => deleteAll(deleteAllArgs, clientArgs),
delete: (deleteArgs: DeleteArgs) => deleteComment(deleteArgs, clientArgs),
find: (findArgs: FindArgs) => find(findArgs, clientArgs),
getAll: (getAllArgs: GetAllArgs) => getAll(getAllArgs, clientArgs),
get: (getArgs: GetArgs) => get(getArgs, clientArgs),
update: (updateArgs: UpdateArgs) => update(updateArgs, clientArgs),
};

return Object.freeze(attachmentSubClient);
Expand Down
Loading