Revert "[Security Solutions] Add PLI authorisation for Cases Connector (#161343)"

This reverts commit aa42bccd40.
This commit is contained in:
Tiago Costa 2023-08-07 10:04:03 +01:00
parent 0fba094cd0
commit c4557ddc43
No known key found for this signature in database
GPG key ID: BAECC2D04A04C6EA
41 changed files with 96 additions and 478 deletions

View file

@ -158,7 +158,6 @@ export const READ_CASES_CAPABILITY = 'read_cases' as const;
export const UPDATE_CASES_CAPABILITY = 'update_cases' as const; export const UPDATE_CASES_CAPABILITY = 'update_cases' as const;
export const DELETE_CASES_CAPABILITY = 'delete_cases' as const; export const DELETE_CASES_CAPABILITY = 'delete_cases' as const;
export const PUSH_CASES_CAPABILITY = 'push_cases' as const; export const PUSH_CASES_CAPABILITY = 'push_cases' as const;
export const CASES_CONNECTORS_CAPABILITY = 'cases_connectors' as const;
/** /**
* Cases API Tags * Cases API Tags
@ -174,11 +173,6 @@ export const SUGGEST_USER_PROFILES_API_TAG = 'casesSuggestUserProfiles';
*/ */
export const BULK_GET_USER_PROFILES_API_TAG = 'bulkGetUserProfiles'; export const BULK_GET_USER_PROFILES_API_TAG = 'bulkGetUserProfiles';
/**
* This tag is registered for the connectors (configure) get API
*/
export const GET_CONNECTORS_CONFIGURE_API_TAG = 'casesGetConnectorsConfigure';
/** /**
* User profiles * User profiles
*/ */

View file

@ -12,8 +12,7 @@ import type {
READ_CASES_CAPABILITY, READ_CASES_CAPABILITY,
UPDATE_CASES_CAPABILITY, UPDATE_CASES_CAPABILITY,
} from '..'; } from '..';
import type { CaseMetricsFeature, CasesMetricsResponse, SingleCaseMetricsResponse } from '../api'; import type { PUSH_CASES_CAPABILITY } from '../constants';
import type { CASES_CONNECTORS_CAPABILITY, PUSH_CASES_CAPABILITY } from '../constants';
import type { SnakeToCamelCase } from '../types'; import type { SnakeToCamelCase } from '../types';
import type { import type {
CaseSeverity, CaseSeverity,
@ -286,7 +285,6 @@ export interface CasesPermissions {
update: boolean; update: boolean;
delete: boolean; delete: boolean;
push: boolean; push: boolean;
connectors: boolean;
} }
export interface CasesCapabilities { export interface CasesCapabilities {
@ -295,5 +293,4 @@ export interface CasesCapabilities {
[UPDATE_CASES_CAPABILITY]: boolean; [UPDATE_CASES_CAPABILITY]: boolean;
[DELETE_CASES_CAPABILITY]: boolean; [DELETE_CASES_CAPABILITY]: boolean;
[PUSH_CASES_CAPABILITY]: boolean; [PUSH_CASES_CAPABILITY]: boolean;
[CASES_CONNECTORS_CAPABILITY]: boolean;
} }

View file

@ -5,7 +5,6 @@ Object {
"all": Array [ "all": Array [
"casesSuggestUserProfiles", "casesSuggestUserProfiles",
"bulkGetUserProfiles", "bulkGetUserProfiles",
"casesGetConnectorsConfigure",
"casesFilesCasesCreate", "casesFilesCasesCreate",
"casesFilesCasesRead", "casesFilesCasesRead",
], ],
@ -15,7 +14,6 @@ Object {
"read": Array [ "read": Array [
"casesSuggestUserProfiles", "casesSuggestUserProfiles",
"bulkGetUserProfiles", "bulkGetUserProfiles",
"casesGetConnectorsConfigure",
"casesFilesCasesRead", "casesFilesCasesRead",
], ],
} }
@ -26,7 +24,6 @@ Object {
"all": Array [ "all": Array [
"casesSuggestUserProfiles", "casesSuggestUserProfiles",
"bulkGetUserProfiles", "bulkGetUserProfiles",
"casesGetConnectorsConfigure",
"observabilityFilesCasesCreate", "observabilityFilesCasesCreate",
"observabilityFilesCasesRead", "observabilityFilesCasesRead",
], ],
@ -36,7 +33,6 @@ Object {
"read": Array [ "read": Array [
"casesSuggestUserProfiles", "casesSuggestUserProfiles",
"bulkGetUserProfiles", "bulkGetUserProfiles",
"casesGetConnectorsConfigure",
"observabilityFilesCasesRead", "observabilityFilesCasesRead",
], ],
} }
@ -47,7 +43,6 @@ Object {
"all": Array [ "all": Array [
"casesSuggestUserProfiles", "casesSuggestUserProfiles",
"bulkGetUserProfiles", "bulkGetUserProfiles",
"casesGetConnectorsConfigure",
"securitySolutionFilesCasesCreate", "securitySolutionFilesCasesCreate",
"securitySolutionFilesCasesRead", "securitySolutionFilesCasesRead",
], ],
@ -57,7 +52,6 @@ Object {
"read": Array [ "read": Array [
"casesSuggestUserProfiles", "casesSuggestUserProfiles",
"bulkGetUserProfiles", "bulkGetUserProfiles",
"casesGetConnectorsConfigure",
"securitySolutionFilesCasesRead", "securitySolutionFilesCasesRead",
], ],
} }

View file

@ -5,11 +5,7 @@
* 2.0. * 2.0.
*/ */
import { import { BULK_GET_USER_PROFILES_API_TAG, SUGGEST_USER_PROFILES_API_TAG } from '../constants';
BULK_GET_USER_PROFILES_API_TAG,
GET_CONNECTORS_CONFIGURE_API_TAG,
SUGGEST_USER_PROFILES_API_TAG,
} from '../constants';
import { HttpApiTagOperation } from '../constants/types'; import { HttpApiTagOperation } from '../constants/types';
import type { Owner } from '../constants/types'; import type { Owner } from '../constants/types';
import { constructFilesHttpOperationTag } from '../files'; import { constructFilesHttpOperationTag } from '../files';
@ -20,19 +16,8 @@ export const getApiTags = (owner: Owner) => {
const read = constructFilesHttpOperationTag(owner, HttpApiTagOperation.Read); const read = constructFilesHttpOperationTag(owner, HttpApiTagOperation.Read);
return { return {
all: [ all: [SUGGEST_USER_PROFILES_API_TAG, BULK_GET_USER_PROFILES_API_TAG, create, read] as const,
SUGGEST_USER_PROFILES_API_TAG, read: [SUGGEST_USER_PROFILES_API_TAG, BULK_GET_USER_PROFILES_API_TAG, read] as const,
BULK_GET_USER_PROFILES_API_TAG,
GET_CONNECTORS_CONFIGURE_API_TAG,
create,
read,
] as const,
read: [
SUGGEST_USER_PROFILES_API_TAG,
BULK_GET_USER_PROFILES_API_TAG,
GET_CONNECTORS_CONFIGURE_API_TAG,
read,
] as const,
delete: [deleteTag] as const, delete: [deleteTag] as const,
}; };
}; };

View file

@ -6,7 +6,6 @@
*/ */
import { import {
CASES_CONNECTORS_CAPABILITY,
CREATE_CASES_CAPABILITY, CREATE_CASES_CAPABILITY,
DELETE_CASES_CAPABILITY, DELETE_CASES_CAPABILITY,
PUSH_CASES_CAPABILITY, PUSH_CASES_CAPABILITY,
@ -24,8 +23,7 @@ export const createUICapabilities = () => ({
READ_CASES_CAPABILITY, READ_CASES_CAPABILITY,
UPDATE_CASES_CAPABILITY, UPDATE_CASES_CAPABILITY,
PUSH_CASES_CAPABILITY, PUSH_CASES_CAPABILITY,
CASES_CONNECTORS_CAPABILITY,
] as const, ] as const,
read: [READ_CASES_CAPABILITY, CASES_CONNECTORS_CAPABILITY] as const, read: [READ_CASES_CAPABILITY] as const,
delete: [DELETE_CASES_CAPABILITY] as const, delete: [DELETE_CASES_CAPABILITY] as const,
}); });

View file

@ -11,8 +11,8 @@ import {
allCasesPermissions, allCasesPermissions,
noCasesCapabilities, noCasesCapabilities,
noCasesPermissions, noCasesPermissions,
readCasesPermissions,
readCasesCapabilities, readCasesCapabilities,
readCasesPermissions,
writeCasesCapabilities, writeCasesCapabilities,
writeCasesPermissions, writeCasesPermissions,
} from '../../common/mock'; } from '../../common/mock';
@ -77,12 +77,6 @@ const hasSecurityWriteAndObservabilityRead: CasesCapabilities = {
generalCases: noCasesCapabilities(), generalCases: noCasesCapabilities(),
}; };
const hasSecurityConnectors: CasesCapabilities = {
securitySolutionCases: readCasesCapabilities(),
observabilityCases: noCasesCapabilities(),
generalCases: noCasesCapabilities(),
};
describe('canUseCases', () => { describe('canUseCases', () => {
it.each([hasAll, hasSecurity, hasObservability, hasSecurityWriteAndObservabilityRead])( it.each([hasAll, hasSecurity, hasObservability, hasSecurityWriteAndObservabilityRead])(
'returns true for all permissions, if a user has access to both on any solution', 'returns true for all permissions, if a user has access to both on any solution',
@ -115,12 +109,4 @@ describe('canUseCases', () => {
expect(permissions).toStrictEqual(noCasesPermissions()); expect(permissions).toStrictEqual(noCasesPermissions());
} }
); );
it.each([hasSecurityConnectors])(
'returns true for only connectors, if a user has access to only connectors on any solution',
(capability) => {
const permissions = canUseCases(capability)();
expect(permissions).toStrictEqual(readCasesPermissions());
}
);
}); });

View file

@ -40,10 +40,8 @@ export const canUseCases =
acc.update = acc.update || userCapabilitiesForOwner.update; acc.update = acc.update || userCapabilitiesForOwner.update;
acc.delete = acc.delete || userCapabilitiesForOwner.delete; acc.delete = acc.delete || userCapabilitiesForOwner.delete;
acc.push = acc.push || userCapabilitiesForOwner.push; acc.push = acc.push || userCapabilitiesForOwner.push;
const allFromAcc = const allFromAcc = acc.create && acc.read && acc.update && acc.delete && acc.push;
acc.create && acc.read && acc.update && acc.delete && acc.push && acc.connectors;
acc.all = acc.all || userCapabilitiesForOwner.all || allFromAcc; acc.all = acc.all || userCapabilitiesForOwner.all || allFromAcc;
acc.connectors = acc.connectors || userCapabilitiesForOwner.connectors;
return acc; return acc;
}, },
@ -54,7 +52,6 @@ export const canUseCases =
update: false, update: false,
delete: false, delete: false,
push: false, push: false,
connectors: false,
} }
); );

View file

@ -12,7 +12,6 @@ describe('getUICapabilities', () => {
expect(getUICapabilities(undefined)).toMatchInlineSnapshot(` expect(getUICapabilities(undefined)).toMatchInlineSnapshot(`
Object { Object {
"all": false, "all": false,
"connectors": false,
"create": false, "create": false,
"delete": false, "delete": false,
"push": false, "push": false,
@ -26,7 +25,6 @@ describe('getUICapabilities', () => {
expect(getUICapabilities()).toMatchInlineSnapshot(` expect(getUICapabilities()).toMatchInlineSnapshot(`
Object { Object {
"all": false, "all": false,
"connectors": false,
"create": false, "create": false,
"delete": false, "delete": false,
"push": false, "push": false,
@ -40,7 +38,6 @@ describe('getUICapabilities', () => {
expect(getUICapabilities({ create_cases: true })).toMatchInlineSnapshot(` expect(getUICapabilities({ create_cases: true })).toMatchInlineSnapshot(`
Object { Object {
"all": false, "all": false,
"connectors": false,
"create": true, "create": true,
"delete": false, "delete": false,
"push": false, "push": false,
@ -58,12 +55,10 @@ describe('getUICapabilities', () => {
update_cases: false, update_cases: false,
delete_cases: false, delete_cases: false,
push_cases: false, push_cases: false,
cases_connectors: false,
}) })
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
Object { Object {
"all": false, "all": false,
"connectors": false,
"create": false, "create": false,
"delete": false, "delete": false,
"push": false, "push": false,
@ -77,7 +72,6 @@ describe('getUICapabilities', () => {
expect(getUICapabilities({})).toMatchInlineSnapshot(` expect(getUICapabilities({})).toMatchInlineSnapshot(`
Object { Object {
"all": false, "all": false,
"connectors": false,
"create": false, "create": false,
"delete": false, "delete": false,
"push": false, "push": false,
@ -95,35 +89,10 @@ describe('getUICapabilities', () => {
update_cases: true, update_cases: true,
delete_cases: true, delete_cases: true,
push_cases: true, push_cases: true,
cases_connectors: true,
}) })
).toMatchInlineSnapshot(` ).toMatchInlineSnapshot(`
Object { Object {
"all": false, "all": false,
"connectors": true,
"create": false,
"delete": true,
"push": true,
"read": true,
"update": true,
}
`);
});
it('returns false for the all field when cases_connectors is false', () => {
expect(
getUICapabilities({
create_cases: false,
read_cases: true,
update_cases: true,
delete_cases: true,
push_cases: true,
cases_connectors: false,
})
).toMatchInlineSnapshot(`
Object {
"all": false,
"connectors": false,
"create": false, "create": false,
"delete": true, "delete": true,
"push": true, "push": true,

View file

@ -7,7 +7,6 @@
import type { CasesPermissions } from '../../../common'; import type { CasesPermissions } from '../../../common';
import { import {
CASES_CONNECTORS_CAPABILITY,
CREATE_CASES_CAPABILITY, CREATE_CASES_CAPABILITY,
DELETE_CASES_CAPABILITY, DELETE_CASES_CAPABILITY,
PUSH_CASES_CAPABILITY, PUSH_CASES_CAPABILITY,
@ -23,8 +22,7 @@ export const getUICapabilities = (
const update = !!featureCapabilities?.[UPDATE_CASES_CAPABILITY]; const update = !!featureCapabilities?.[UPDATE_CASES_CAPABILITY];
const deletePriv = !!featureCapabilities?.[DELETE_CASES_CAPABILITY]; const deletePriv = !!featureCapabilities?.[DELETE_CASES_CAPABILITY];
const push = !!featureCapabilities?.[PUSH_CASES_CAPABILITY]; const push = !!featureCapabilities?.[PUSH_CASES_CAPABILITY];
const connectors = !!featureCapabilities?.[CASES_CONNECTORS_CAPABILITY]; const all = create && read && update && deletePriv && push;
const all = create && read && update && deletePriv && push && connectors;
return { return {
all, all,
@ -33,6 +31,5 @@ export const getUICapabilities = (
update, update,
delete: deletePriv, delete: deletePriv,
push, push,
connectors,
}; };
}; };

View file

@ -193,7 +193,6 @@ export const useApplicationCapabilities = (): UseApplicationCapabilities => {
update: permissions.update, update: permissions.update,
delete: permissions.delete, delete: permissions.delete,
push: permissions.push, push: permissions.push,
connectors: permissions.connectors,
}, },
visualize: { crud: !!capabilities.visualize?.save, read: !!capabilities.visualize?.show }, visualize: { crud: !!capabilities.visualize?.save, read: !!capabilities.visualize?.show },
dashboard: { dashboard: {
@ -214,7 +213,6 @@ export const useApplicationCapabilities = (): UseApplicationCapabilities => {
permissions.update, permissions.update,
permissions.delete, permissions.delete,
permissions.push, permissions.push,
permissions.connectors,
] ]
); );
}; };

View file

@ -74,7 +74,6 @@ export const createStartServicesMock = ({ license }: StartServiceArgs = {}): Sta
update_cases: true, update_cases: true,
delete_cases: true, delete_cases: true,
push_cases: true, push_cases: true,
cases_connectors: true,
}, },
visualize: { save: true, show: true }, visualize: { save: true, show: true },
dashboard: { show: true, createNew: true }, dashboard: { show: true, createNew: true },

View file

@ -9,23 +9,9 @@ import type { CasesCapabilities, CasesPermissions } from '../../containers/types
export const allCasesPermissions = () => buildCasesPermissions(); export const allCasesPermissions = () => buildCasesPermissions();
export const noCasesPermissions = () => export const noCasesPermissions = () =>
buildCasesPermissions({ buildCasesPermissions({ read: false, create: false, update: false, delete: false, push: false });
read: false,
create: false,
update: false,
delete: false,
push: false,
connectors: false,
});
export const readCasesPermissions = () => export const readCasesPermissions = () =>
buildCasesPermissions({ buildCasesPermissions({ read: true, create: false, update: false, delete: false, push: false });
read: true,
create: false,
update: false,
delete: false,
push: false,
connectors: true,
});
export const noCreateCasesPermissions = () => buildCasesPermissions({ create: false }); export const noCreateCasesPermissions = () => buildCasesPermissions({ create: false });
export const noUpdateCasesPermissions = () => buildCasesPermissions({ update: false }); export const noUpdateCasesPermissions = () => buildCasesPermissions({ update: false });
export const noPushCasesPermissions = () => buildCasesPermissions({ push: false }); export const noPushCasesPermissions = () => buildCasesPermissions({ push: false });
@ -33,7 +19,6 @@ export const noDeleteCasesPermissions = () => buildCasesPermissions({ delete: fa
export const writeCasesPermissions = () => buildCasesPermissions({ read: false }); export const writeCasesPermissions = () => buildCasesPermissions({ read: false });
export const onlyDeleteCasesPermission = () => export const onlyDeleteCasesPermission = () =>
buildCasesPermissions({ read: false, create: false, update: false, delete: true, push: false }); buildCasesPermissions({ read: false, create: false, update: false, delete: true, push: false });
export const noConnectorsCasePermission = () => buildCasesPermissions({ connectors: false });
export const buildCasesPermissions = (overrides: Partial<Omit<CasesPermissions, 'all'>> = {}) => { export const buildCasesPermissions = (overrides: Partial<Omit<CasesPermissions, 'all'>> = {}) => {
const create = overrides.create ?? true; const create = overrides.create ?? true;
@ -41,7 +26,6 @@ export const buildCasesPermissions = (overrides: Partial<Omit<CasesPermissions,
const update = overrides.update ?? true; const update = overrides.update ?? true;
const deletePermissions = overrides.delete ?? true; const deletePermissions = overrides.delete ?? true;
const push = overrides.push ?? true; const push = overrides.push ?? true;
const connectors = overrides.connectors ?? true;
const all = create && read && update && deletePermissions && push; const all = create && read && update && deletePermissions && push;
return { return {
@ -51,7 +35,6 @@ export const buildCasesPermissions = (overrides: Partial<Omit<CasesPermissions,
update, update,
delete: deletePermissions, delete: deletePermissions,
push, push,
connectors,
}; };
}; };
@ -63,7 +46,6 @@ export const noCasesCapabilities = () =>
update_cases: false, update_cases: false,
delete_cases: false, delete_cases: false,
push_cases: false, push_cases: false,
cases_connectors: false,
}); });
export const readCasesCapabilities = () => export const readCasesCapabilities = () =>
buildCasesCapabilities({ buildCasesCapabilities({
@ -85,6 +67,5 @@ export const buildCasesCapabilities = (overrides?: Partial<CasesCapabilities>) =
update_cases: overrides?.update_cases ?? true, update_cases: overrides?.update_cases ?? true,
delete_cases: overrides?.delete_cases ?? true, delete_cases: overrides?.delete_cases ?? true,
push_cases: overrides?.push_cases ?? true, push_cases: overrides?.push_cases ?? true,
cases_connectors: overrides?.cases_connectors ?? true,
}; };
}; };

View file

@ -12,12 +12,8 @@ import { render, screen } from '@testing-library/react';
import type { Props } from './connectors'; import type { Props } from './connectors';
import { Connectors } from './connectors'; import { Connectors } from './connectors';
import { import type { AppMockRenderer } from '../../common/mock';
type AppMockRenderer, import { createAppMockRenderer, TestProviders } from '../../common/mock';
noConnectorsCasePermission,
createAppMockRenderer,
TestProviders,
} from '../../common/mock';
import { ConnectorsDropdown } from './connectors_dropdown'; import { ConnectorsDropdown } from './connectors_dropdown';
import { connectors, actionTypes } from './__mock__'; import { connectors, actionTypes } from './__mock__';
import { ConnectorTypes } from '../../../common/types/domain'; import { ConnectorTypes } from '../../../common/types/domain';
@ -165,14 +161,4 @@ describe('Connectors', () => {
).toBeInTheDocument(); ).toBeInTheDocument();
expect(result.queryByTestId('case-connectors-dropdown')).toBe(null); expect(result.queryByTestId('case-connectors-dropdown')).toBe(null);
}); });
it('shows the actions permission message if the user does not have access to case connector', async () => {
appMockRender = createAppMockRenderer({ permissions: noConnectorsCasePermission() });
const result = appMockRender.render(<Connectors {...props} />);
expect(
result.getByTestId('configure-case-connector-permissions-error-msg')
).toBeInTheDocument();
expect(result.queryByTestId('case-connectors-dropdown')).toBe(null);
});
}); });

View file

@ -27,7 +27,6 @@ import { ConnectorTypes } from '../../../common/types/domain';
import { DeprecatedCallout } from '../connectors/deprecated_callout'; import { DeprecatedCallout } from '../connectors/deprecated_callout';
import { isDeprecatedConnector } from '../utils'; import { isDeprecatedConnector } from '../utils';
import { useApplicationCapabilities } from '../../common/lib/kibana'; import { useApplicationCapabilities } from '../../common/lib/kibana';
import { useCasesContext } from '../cases_context/use_cases_context';
const EuiFormRowExtended = styled(EuiFormRow)` const EuiFormRowExtended = styled(EuiFormRow)`
.euiFormRow__labelWrapper { .euiFormRow__labelWrapper {
@ -64,8 +63,6 @@ const ConnectorsComponent: React.FC<Props> = ({
() => connectors.find((c) => c.id === selectedConnector.id), () => connectors.find((c) => c.id === selectedConnector.id),
[connectors, selectedConnector.id] [connectors, selectedConnector.id]
); );
const { permissions } = useCasesContext();
const canUseConnectors = permissions.connectors && actions.read;
const connectorsName = connector?.name ?? 'none'; const connectorsName = connector?.name ?? 'none';
@ -108,7 +105,7 @@ const ConnectorsComponent: React.FC<Props> = ({
> >
<EuiFlexGroup direction="column"> <EuiFlexGroup direction="column">
<EuiFlexItem grow={false}> <EuiFlexItem grow={false}>
{canUseConnectors ? ( {actions.read ? (
<ConnectorsDropdown <ConnectorsDropdown
connectors={connectors} connectors={connectors}
disabled={disabled} disabled={disabled}

View file

@ -22,11 +22,7 @@ import { incidentTypes, severity, choices } from '../connectors/mock';
import type { FormProps } from './schema'; import type { FormProps } from './schema';
import { schema } from './schema'; import { schema } from './schema';
import type { AppMockRenderer } from '../../common/mock'; import type { AppMockRenderer } from '../../common/mock';
import { import { createAppMockRenderer, TestProviders } from '../../common/mock';
noConnectorsCasePermission,
createAppMockRenderer,
TestProviders,
} from '../../common/mock';
import { useCaseConfigure } from '../../containers/configure/use_configure'; import { useCaseConfigure } from '../../containers/configure/use_configure';
import { useCaseConfigureResponse } from '../configure_cases/__mock__'; import { useCaseConfigureResponse } from '../configure_cases/__mock__';
@ -194,16 +190,4 @@ describe('Connector', () => {
expect(result.getByTestId('create-case-connector-permissions-error-msg')).toBeInTheDocument(); expect(result.getByTestId('create-case-connector-permissions-error-msg')).toBeInTheDocument();
expect(result.queryByTestId('caseConnectors')).toBe(null); expect(result.queryByTestId('caseConnectors')).toBe(null);
}); });
it('shows the actions permission message if the user does not have access to case connector', async () => {
appMockRender = createAppMockRenderer({ permissions: noConnectorsCasePermission() });
const result = appMockRender.render(
<MockHookWrapperComponent>
<Connector {...defaultProps} />
</MockHookWrapperComponent>
);
expect(result.getByTestId('create-case-connector-permissions-error-msg')).toBeInTheDocument();
expect(result.queryByTestId('caseConnectors')).toBe(null);
});
}); });

View file

@ -18,7 +18,6 @@ import { useCaseConfigure } from '../../containers/configure/use_configure';
import { getConnectorById, getConnectorsFormValidators } from '../utils'; import { getConnectorById, getConnectorsFormValidators } from '../utils';
import { useApplicationCapabilities } from '../../common/lib/kibana'; import { useApplicationCapabilities } from '../../common/lib/kibana';
import * as i18n from '../../common/translations'; import * as i18n from '../../common/translations';
import { useCasesContext } from '../cases_context/use_cases_context';
interface Props { interface Props {
connectors: ActionConnector[]; connectors: ActionConnector[];
@ -31,8 +30,6 @@ const ConnectorComponent: React.FC<Props> = ({ connectors, isLoading, isLoadingC
const connector = getConnectorById(connectorId, connectors) ?? null; const connector = getConnectorById(connectorId, connectors) ?? null;
const { connector: configurationConnector } = useCaseConfigure(); const { connector: configurationConnector } = useCaseConfigure();
const { actions } = useApplicationCapabilities(); const { actions } = useApplicationCapabilities();
const { permissions } = useCasesContext();
const hasReadPermissions = permissions.connectors && actions.read;
const defaultConnectorId = useMemo(() => { const defaultConnectorId = useMemo(() => {
return connectors.some((c) => c.id === configurationConnector.id) return connectors.some((c) => c.id === configurationConnector.id)
@ -45,7 +42,7 @@ const ConnectorComponent: React.FC<Props> = ({ connectors, isLoading, isLoadingC
connectors, connectors,
}); });
if (!hasReadPermissions) { if (!actions.read) {
return ( return (
<EuiText data-test-subj="create-case-connector-permissions-error-msg" size="s"> <EuiText data-test-subj="create-case-connector-permissions-error-msg" size="s">
<span>{i18n.READ_ACTIONS_PERMISSIONS_ERROR_MSG}</span> <span>{i18n.READ_ACTIONS_PERMISSIONS_ERROR_MSG}</span>

View file

@ -11,14 +11,12 @@ import userEvent from '@testing-library/user-event';
import type { EditConnectorProps } from '.'; import type { EditConnectorProps } from '.';
import { EditConnector } from '.'; import { EditConnector } from '.';
import type { AppMockRenderer } from '../../common/mock';
import { import {
type AppMockRenderer,
createAppMockRenderer, createAppMockRenderer,
readCasesPermissions, readCasesPermissions,
noPushCasesPermissions, noPushCasesPermissions,
TestProviders, TestProviders,
noConnectorsCasePermission,
} from '../../common/mock'; } from '../../common/mock';
import { basicCase, connectorsMock } from '../../containers/mock'; import { basicCase, connectorsMock } from '../../containers/mock';
import { getCaseConnectorsMockResponse } from '../../common/mock/connectors'; import { getCaseConnectorsMockResponse } from '../../common/mock/connectors';
@ -276,17 +274,6 @@ describe('EditConnector ', () => {
}); });
}); });
it('does not show the callout if the user does not have access to cases connectors', async () => {
const props = { ...defaultProps, connectors: [] };
appMockRender = createAppMockRenderer({ permissions: noConnectorsCasePermission() });
const result = appMockRender.render(<EditConnector {...props} />);
await waitFor(() => {
expect(result.getByTestId('edit-connector-permissions-error-msg')).toBeInTheDocument();
expect(result.queryByTestId('push-callouts')).toBe(null);
});
});
it('does not show the connectors previewer if the user does not have read access to actions', async () => { it('does not show the connectors previewer if the user does not have read access to actions', async () => {
const props = { ...defaultProps, connectors: [] }; const props = { ...defaultProps, connectors: [] };
appMockRender.coreStart.application.capabilities = { appMockRender.coreStart.application.capabilities = {
@ -298,14 +285,6 @@ describe('EditConnector ', () => {
expect(result.queryByTestId('connector-fields-preview')).not.toBeInTheDocument(); expect(result.queryByTestId('connector-fields-preview')).not.toBeInTheDocument();
}); });
it('does not show the connectors previewer if the user does not have access to cases connectors', async () => {
const props = { ...defaultProps, connectors: [] };
appMockRender = createAppMockRenderer({ permissions: noConnectorsCasePermission() });
const result = appMockRender.render(<EditConnector {...props} />);
expect(result.queryByTestId('connector-fields-preview')).not.toBeInTheDocument();
});
it('does not show the connectors form if the user does not have read access to actions', async () => { it('does not show the connectors form if the user does not have read access to actions', async () => {
const props = { ...defaultProps, connectors: [] }; const props = { ...defaultProps, connectors: [] };
appMockRender.coreStart.application.capabilities = { appMockRender.coreStart.application.capabilities = {
@ -317,14 +296,6 @@ describe('EditConnector ', () => {
expect(result.queryByTestId('edit-connector-fields-form-flex-item')).not.toBeInTheDocument(); expect(result.queryByTestId('edit-connector-fields-form-flex-item')).not.toBeInTheDocument();
}); });
it('does not show the connectors form if the user does not have access to cases connectors', async () => {
const props = { ...defaultProps, connectors: [] };
appMockRender = createAppMockRenderer({ permissions: noConnectorsCasePermission() });
const result = appMockRender.render(<EditConnector {...props} />);
expect(result.queryByTestId('edit-connector-fields-form-flex-item')).not.toBeInTheDocument();
});
it('does not show the push button if the user does not have read access to actions', async () => { it('does not show the push button if the user does not have read access to actions', async () => {
appMockRender.coreStart.application.capabilities = { appMockRender.coreStart.application.capabilities = {
...appMockRender.coreStart.application.capabilities, ...appMockRender.coreStart.application.capabilities,
@ -346,15 +317,6 @@ describe('EditConnector ', () => {
}); });
}); });
it('does not show the push button if the user does not have access to cases actions', async () => {
appMockRender = createAppMockRenderer({ permissions: noConnectorsCasePermission() });
const result = appMockRender.render(<EditConnector {...defaultProps} />);
await waitFor(() => {
expect(result.queryByTestId('push-to-external-service')).toBe(null);
});
});
it('does not show the edit connectors pencil if the user does not have read access to actions', async () => { it('does not show the edit connectors pencil if the user does not have read access to actions', async () => {
const props = { ...defaultProps, connectors: [] }; const props = { ...defaultProps, connectors: [] };
appMockRender.coreStart.application.capabilities = { appMockRender.coreStart.application.capabilities = {
@ -370,20 +332,6 @@ describe('EditConnector ', () => {
}); });
}); });
it('does not show the edit connectors pencil if the user does not have access to case connectors', async () => {
const props = { ...defaultProps, connectors: [] };
appMockRender = createAppMockRenderer({
permissions: noConnectorsCasePermission(),
});
appMockRender.render(<EditConnector {...props} />);
await waitFor(() => {
expect(screen.getByTestId('connector-edit-header')).toBeInTheDocument();
expect(screen.queryByTestId('connector-edit-button')).not.toBeInTheDocument();
});
});
it('does not show the edit connectors pencil if the user does not have push permissions', async () => { it('does not show the edit connectors pencil if the user does not have push permissions', async () => {
const props = { ...defaultProps, connectors: [] }; const props = { ...defaultProps, connectors: [] };
appMockRender = createAppMockRenderer({ permissions: noPushCasesPermissions() }); appMockRender = createAppMockRenderer({ permissions: noPushCasesPermissions() });

View file

@ -21,7 +21,6 @@ import { PushButton } from './push_button';
import { PushCallouts } from './push_callouts'; import { PushCallouts } from './push_callouts';
import { ConnectorsForm } from './connectors_form'; import { ConnectorsForm } from './connectors_form';
import { ConnectorFieldsPreviewForm } from '../connectors/fields_preview_form'; import { ConnectorFieldsPreviewForm } from '../connectors/fields_preview_form';
import { useCasesContext } from '../cases_context/use_cases_context';
export interface EditConnectorProps { export interface EditConnectorProps {
caseData: CaseUI; caseData: CaseUI;
@ -46,8 +45,7 @@ export const EditConnector = React.memo(
const [isEdit, setIsEdit] = useState(false); const [isEdit, setIsEdit] = useState(false);
const { actions } = useApplicationCapabilities(); const { actions } = useApplicationCapabilities();
const { permissions } = useCasesContext(); const hasActionsReadPermissions = actions.read;
const canUseConnectors = permissions.connectors && actions.read;
const onEditClick = useCallback(() => setIsEdit(true), []); const onEditClick = useCallback(() => setIsEdit(true), []);
const onCancelConnector = useCallback(() => setIsEdit(false), []); const onCancelConnector = useCallback(() => setIsEdit(false), []);
@ -104,7 +102,7 @@ export const EditConnector = React.memo(
<EuiFlexItem grow={false} data-test-subj="connector-edit-header"> <EuiFlexItem grow={false} data-test-subj="connector-edit-header">
<h4>{i18n.CONNECTORS}</h4> <h4>{i18n.CONNECTORS}</h4>
</EuiFlexItem> </EuiFlexItem>
{!isLoading && !isEdit && hasPushPermissions && canUseConnectors ? ( {!isLoading && !isEdit && hasPushPermissions && hasActionsReadPermissions ? (
<EuiFlexItem data-test-subj="connector-edit" grow={false}> <EuiFlexItem data-test-subj="connector-edit" grow={false}>
<EuiButtonIcon <EuiButtonIcon
data-test-subj="connector-edit-button" data-test-subj="connector-edit-button"
@ -117,7 +115,7 @@ export const EditConnector = React.memo(
</EuiFlexGroup> </EuiFlexGroup>
<EuiHorizontalRule margin="xs" /> <EuiHorizontalRule margin="xs" />
<EuiFlexGroup data-test-subj="edit-connectors" direction="column" alignItems="stretch"> <EuiFlexGroup data-test-subj="edit-connectors" direction="column" alignItems="stretch">
{!isLoading && !isEdit && hasErrorMessages && canUseConnectors && ( {!isLoading && !isEdit && hasErrorMessages && hasActionsReadPermissions && (
<EuiFlexItem data-test-subj="push-callouts"> <EuiFlexItem data-test-subj="push-callouts">
<PushCallouts <PushCallouts
errorsMsg={errorsMsg} errorsMsg={errorsMsg}
@ -127,18 +125,18 @@ export const EditConnector = React.memo(
/> />
</EuiFlexItem> </EuiFlexItem>
)} )}
{!canUseConnectors && ( {!hasActionsReadPermissions && (
<EuiText data-test-subj="edit-connector-permissions-error-msg" size="s"> <EuiText data-test-subj="edit-connector-permissions-error-msg" size="s">
<span>{i18n.READ_ACTIONS_PERMISSIONS_ERROR_MSG}</span> <span>{i18n.READ_ACTIONS_PERMISSIONS_ERROR_MSG}</span>
</EuiText> </EuiText>
)} )}
{canUseConnectors && !isEdit && ( {hasActionsReadPermissions && !isEdit && (
<ConnectorFieldsPreviewForm <ConnectorFieldsPreviewForm
connector={caseActionConnector} connector={caseActionConnector}
fields={caseConnectorFields} fields={caseConnectorFields}
/> />
)} )}
{canUseConnectors && isEdit && ( {hasActionsReadPermissions && isEdit && (
<ConnectorsForm <ConnectorsForm
caseData={caseData} caseData={caseData}
caseConnectors={caseConnectors} caseConnectors={caseConnectors}
@ -148,21 +146,25 @@ export const EditConnector = React.memo(
onSubmit={onSubmitConnector} onSubmit={onSubmitConnector}
/> />
)} )}
{!hasErrorMessages && !isLoading && !isEdit && hasPushPermissions && canUseConnectors && ( {!hasErrorMessages &&
<EuiFlexItem grow={false}> !isLoading &&
<span> !isEdit &&
<PushButton hasPushPermissions &&
hasBeenPushed={hasBeenPushed} hasActionsReadPermissions && (
disabled={disablePushButton} <EuiFlexItem grow={false}>
isLoading={isLoadingPushToService} <span>
pushToService={handlePushToService} <PushButton
errorsMsg={errorsMsg} hasBeenPushed={hasBeenPushed}
showTooltip={errorsMsg.length > 0 || !needsToBePushed || !hasPushPermissions} disabled={disablePushButton}
connectorName={connectorWithName.name} isLoading={isLoadingPushToService}
/> pushToService={handlePushToService}
</span> errorsMsg={errorsMsg}
</EuiFlexItem> showTooltip={errorsMsg.length > 0 || !needsToBePushed || !hasPushPermissions}
)} connectorName={connectorWithName.name}
/>
</span>
</EuiFlexItem>
)}
</EuiFlexGroup> </EuiFlexGroup>
</EuiText> </EuiText>
</EuiFlexItem> </EuiFlexItem>

View file

@ -11,17 +11,14 @@ import { useApplicationCapabilities, useToasts } from '../../common/lib/kibana';
import * as i18n from './translations'; import * as i18n from './translations';
import { casesQueriesKeys } from '../constants'; import { casesQueriesKeys } from '../constants';
import type { ServerError } from '../../types'; import type { ServerError } from '../../types';
import { useCasesContext } from '../../components/cases_context/use_cases_context';
export function useGetSupportedActionConnectors() { export function useGetSupportedActionConnectors() {
const toasts = useToasts(); const toasts = useToasts();
const { actions } = useApplicationCapabilities(); const { actions } = useApplicationCapabilities();
const { permissions } = useCasesContext();
return useQuery( return useQuery(
casesQueriesKeys.connectorsList(), casesQueriesKeys.connectorsList(),
async ({ signal }) => { async ({ signal }) => {
if (!actions.read || !permissions.connectors) { if (!actions.read) {
return []; return [];
} }
return getSupportedActionConnectors({ signal }); return getSupportedActionConnectors({ signal });

View file

@ -8,7 +8,7 @@
import React from 'react'; import React from 'react';
import { renderHook } from '@testing-library/react-hooks'; import { renderHook } from '@testing-library/react-hooks';
import * as api from './api'; import * as api from './api';
import { noConnectorsCasePermission, TestProviders } from '../../common/mock'; import { TestProviders } from '../../common/mock';
import { useApplicationCapabilities, useToasts } from '../../common/lib/kibana'; import { useApplicationCapabilities, useToasts } from '../../common/lib/kibana';
import { useGetSupportedActionConnectors } from './use_get_supported_action_connectors'; import { useGetSupportedActionConnectors } from './use_get_supported_action_connectors';
@ -65,20 +65,4 @@ describe('useConnectors', () => {
expect(spyOnFetchConnectors).not.toHaveBeenCalled(); expect(spyOnFetchConnectors).not.toHaveBeenCalled();
expect(result.current.data).toEqual([]); expect(result.current.data).toEqual([]);
}); });
it('does not fetch connectors when the user does not has access to connectors', async () => {
const spyOnFetchConnectors = jest.spyOn(api, 'getSupportedActionConnectors');
useApplicationCapabilitiesMock().actions = { crud: true, read: true };
const { result, waitForNextUpdate } = renderHook(() => useGetSupportedActionConnectors(), {
wrapper: ({ children }) => (
<TestProviders permissions={noConnectorsCasePermission()}>{children}</TestProviders>
),
});
await waitForNextUpdate();
expect(spyOnFetchConnectors).not.toHaveBeenCalled();
expect(result.current.data).toEqual([]);
});
}); });

View file

@ -2458,7 +2458,7 @@ Object {
"type": "cases", "type": "cases",
}, },
}, },
"message": "Failed attempt to push cases [id=1] as owner \\"awesome\\"", "message": "Failed attempt to update cases [id=1] as owner \\"awesome\\"",
} }
`; `;
@ -2478,7 +2478,7 @@ Object {
"change", "change",
], ],
}, },
"message": "Failed attempt to push a case as any owners", "message": "Failed attempt to update a case as any owners",
} }
`; `;
@ -2500,7 +2500,7 @@ Object {
"type": "cases", "type": "cases",
}, },
}, },
"message": "User is pushing cases [id=5] as owner \\"super\\"", "message": "User is updating cases [id=5] as owner \\"super\\"",
} }
`; `;
@ -2516,7 +2516,7 @@ Object {
"change", "change",
], ],
}, },
"message": "User is pushing a case as any owners", "message": "User is updating a case as any owners",
} }
`; `;

View file

@ -39,12 +39,6 @@ const updateVerbs: Verbs = {
past: 'updated', past: 'updated',
}; };
const pushVerbs: Verbs = {
present: 'push',
progressive: 'pushing',
past: 'pushed',
};
const deleteVerbs: Verbs = { const deleteVerbs: Verbs = {
present: 'delete', present: 'delete',
progressive: 'deleting', progressive: 'deleting',
@ -170,7 +164,7 @@ const CaseOperations = {
ecsType: EVENT_TYPES.change, ecsType: EVENT_TYPES.change,
name: WriteOperations.PushCase as const, name: WriteOperations.PushCase as const,
action: 'case_push', action: 'case_push',
verbs: pushVerbs, verbs: updateVerbs,
docType: 'case', docType: 'case',
savedObjectType: CASE_SAVED_OBJECT, savedObjectType: CASE_SAVED_OBJECT,
}, },

View file

@ -15,9 +15,6 @@ import { createCasesRoute } from '../create_cases_route';
export const getConnectorsRoute = createCasesRoute({ export const getConnectorsRoute = createCasesRoute({
method: 'get', method: 'get',
path: `${CASE_CONFIGURE_CONNECTORS_URL}/_find`, path: `${CASE_CONFIGURE_CONNECTORS_URL}/_find`,
routerOptions: {
tags: ['access:casesGetConnectorsConfigure'],
},
handler: async ({ context, response }) => { handler: async ({ context, response }) => {
try { try {
const caseContext = await context.cases; const caseContext = await context.cases;

View file

@ -40,7 +40,7 @@ interface CaseRouteHandlerArguments<P, Q, B> {
kibanaVersion: PluginInitializerContext['env']['packageInfo']['version']; kibanaVersion: PluginInitializerContext['env']['packageInfo']['version'];
} }
type CaseRouteTags = 'access:casesSuggestUserProfiles' | 'access:casesGetConnectorsConfigure'; type CaseRouteTags = 'access:casesSuggestUserProfiles';
export interface CaseRoute<P = unknown, Q = unknown, B = unknown> { export interface CaseRoute<P = unknown, Q = unknown, B = unknown> {
method: 'get' | 'post' | 'put' | 'delete' | 'patch'; method: 'get' | 'post' | 'put' | 'delete' | 'patch';

View file

@ -110,7 +110,6 @@ describe('AddToCaseAction', function () {
update: false, update: false,
delete: false, delete: false,
push: false, push: false,
connectors: false,
}, },
}) })
); );

View file

@ -18,7 +18,6 @@ export function useGetUserCasesPermissions() {
update: false, update: false,
delete: false, delete: false,
push: false, push: false,
connectors: false,
}); });
const uiCapabilities = useKibana().services.application.capabilities; const uiCapabilities = useKibana().services.application.capabilities;
@ -34,7 +33,6 @@ export function useGetUserCasesPermissions() {
update: casesCapabilities.update, update: casesCapabilities.update,
delete: casesCapabilities.delete, delete: casesCapabilities.delete,
push: casesCapabilities.push, push: casesCapabilities.push,
connectors: casesCapabilities.connectors,
}); });
}, [ }, [
casesCapabilities.all, casesCapabilities.all,
@ -43,7 +41,6 @@ export function useGetUserCasesPermissions() {
casesCapabilities.update, casesCapabilities.update,
casesCapabilities.delete, casesCapabilities.delete,
casesCapabilities.push, casesCapabilities.push,
casesCapabilities.connectors,
]); ]);
return casesPermissions; return casesPermissions;

View file

@ -19,15 +19,7 @@ export default {
const Template: ComponentStory<typeof Component> = (props: CasesProps) => <Component {...props} />; const Template: ComponentStory<typeof Component> = (props: CasesProps) => <Component {...props} />;
const defaultProps: CasesProps = { const defaultProps: CasesProps = {
permissions: { permissions: { read: true, all: true, create: true, delete: true, push: true, update: true },
read: true,
all: true,
create: true,
delete: true,
push: true,
update: true,
connectors: true,
},
}; };
export const CasesPageWithAllPermissions = Template.bind({}); export const CasesPageWithAllPermissions = Template.bind({});
@ -42,6 +34,5 @@ CasesPageWithNoPermissions.args = {
delete: false, delete: false,
push: false, push: false,
update: false, update: false,
connectors: false,
}, },
}; };

View file

@ -19,7 +19,6 @@ export function useGetUserCasesPermissions() {
update: false, update: false,
delete: false, delete: false,
push: false, push: false,
connectors: false,
}); });
const uiCapabilities = useKibana().services.application!.capabilities; const uiCapabilities = useKibana().services.application!.capabilities;
@ -36,7 +35,6 @@ export function useGetUserCasesPermissions() {
update: casesCapabilities.update, update: casesCapabilities.update,
delete: casesCapabilities.delete, delete: casesCapabilities.delete,
push: casesCapabilities.push, push: casesCapabilities.push,
connectors: casesCapabilities.connectors,
}); });
}, [ }, [
casesCapabilities.all, casesCapabilities.all,
@ -45,7 +43,6 @@ export function useGetUserCasesPermissions() {
casesCapabilities.update, casesCapabilities.update,
casesCapabilities.delete, casesCapabilities.delete,
casesCapabilities.push, casesCapabilities.push,
casesCapabilities.connectors,
]); ]);
return casesPermissions; return casesPermissions;

View file

@ -12,5 +12,4 @@ export const noCasesPermissions = () => ({
update: false, update: false,
delete: false, delete: false,
push: false, push: false,
connectors: false,
}); });

View file

@ -11,7 +11,6 @@ export const noCasesCapabilities = () => ({
update_cases: false, update_cases: false,
delete_cases: false, delete_cases: false,
push_cases: false, push_cases: false,
cases_connector: false,
}); });
export const readCasesCapabilities = () => ({ export const readCasesCapabilities = () => ({
@ -20,7 +19,6 @@ export const readCasesCapabilities = () => ({
update_cases: false, update_cases: false,
delete_cases: false, delete_cases: false,
push_cases: false, push_cases: false,
cases_connector: true,
}); });
export const allCasesCapabilities = () => ({ export const allCasesCapabilities = () => ({
@ -29,7 +27,6 @@ export const allCasesCapabilities = () => ({
update_cases: true, update_cases: true,
delete_cases: true, delete_cases: true,
push_cases: true, push_cases: true,
cases_connector: true,
}); });
export const noCasesPermissions = () => ({ export const noCasesPermissions = () => ({
@ -39,7 +36,6 @@ export const noCasesPermissions = () => ({
update: false, update: false,
delete: false, delete: false,
push: false, push: false,
connectors: false,
}); });
export const readCasesPermissions = () => ({ export const readCasesPermissions = () => ({
@ -49,7 +45,6 @@ export const readCasesPermissions = () => ({
update: false, update: false,
delete: false, delete: false,
push: false, push: false,
connectors: true,
}); });
export const writeCasesPermissions = () => ({ export const writeCasesPermissions = () => ({
@ -59,7 +54,6 @@ export const writeCasesPermissions = () => ({
update: true, update: true,
delete: true, delete: true,
push: true, push: true,
connectors: true,
}); });
export const allCasesPermissions = () => ({ export const allCasesPermissions = () => ({
@ -69,5 +63,4 @@ export const allCasesPermissions = () => ({
update: true, update: true,
delete: true, delete: true,
push: true, push: true,
connectors: true,
}); });

View file

@ -161,7 +161,6 @@ export const useGetUserCasesPermissions = () => {
update: false, update: false,
delete: false, delete: false,
push: false, push: false,
connectors: false,
}); });
const uiCapabilities = useKibana().services.application.capabilities; const uiCapabilities = useKibana().services.application.capabilities;
const casesCapabilities = useKibana().services.cases.helpers.getUICapabilities( const casesCapabilities = useKibana().services.cases.helpers.getUICapabilities(
@ -176,7 +175,6 @@ export const useGetUserCasesPermissions = () => {
update: casesCapabilities.update, update: casesCapabilities.update,
delete: casesCapabilities.delete, delete: casesCapabilities.delete,
push: casesCapabilities.push, push: casesCapabilities.push,
connectors: casesCapabilities.connectors,
}); });
}, [ }, [
casesCapabilities.all, casesCapabilities.all,
@ -185,7 +183,6 @@ export const useGetUserCasesPermissions = () => {
casesCapabilities.update, casesCapabilities.update,
casesCapabilities.delete, casesCapabilities.delete,
casesCapabilities.push, casesCapabilities.push,
casesCapabilities.connectors,
]); ]);
return casesPermissions; return casesPermissions;

View file

@ -13,10 +13,6 @@ import {
createUICapabilities as createCasesUICapabilities, createUICapabilities as createCasesUICapabilities,
getApiTags as getCasesApiTags, getApiTags as getCasesApiTags,
} from '@kbn/cases-plugin/common'; } from '@kbn/cases-plugin/common';
import {
CASES_CONNECTORS_CAPABILITY,
GET_CONNECTORS_CONFIGURE_API_TAG,
} from '@kbn/cases-plugin/common/constants';
import type { AppFeaturesCasesConfig, BaseKibanaFeatureConfig } from './types'; import type { AppFeaturesCasesConfig, BaseKibanaFeatureConfig } from './types';
import { APP_ID, CASES_FEATURE_ID } from '../../../common/constants'; import { APP_ID, CASES_FEATURE_ID } from '../../../common/constants';
import { CasesSubFeatureId } from './security_cases_kibana_sub_features'; import { CasesSubFeatureId } from './security_cases_kibana_sub_features';
@ -25,66 +21,48 @@ import { AppFeatureCasesKey } from '../../../common/types/app_features';
const casesCapabilities = createCasesUICapabilities(); const casesCapabilities = createCasesUICapabilities();
const casesApiTags = getCasesApiTags(APP_ID); const casesApiTags = getCasesApiTags(APP_ID);
export const getCasesBaseKibanaFeature = (): BaseKibanaFeatureConfig => { export const getCasesBaseKibanaFeature = (): BaseKibanaFeatureConfig => ({
// On SecuritySolution essentials cases does not have the connector feature id: CASES_FEATURE_ID,
const casesAllUICapabilities = casesCapabilities.all.filter( name: i18n.translate('xpack.securitySolution.featureRegistry.linkSecuritySolutionCaseTitle', {
(capability) => capability !== CASES_CONNECTORS_CAPABILITY defaultMessage: 'Cases',
); }),
order: 1100,
const casesReadUICapabilities = casesCapabilities.read.filter( category: DEFAULT_APP_CATEGORIES.security,
(capability) => capability !== CASES_CONNECTORS_CAPABILITY app: [CASES_FEATURE_ID, 'kibana'],
); catalogue: [APP_ID],
cases: [APP_ID],
const casesAllAPICapabilities = casesApiTags.all.filter( privileges: {
(capability) => capability !== GET_CONNECTORS_CONFIGURE_API_TAG all: {
); api: casesApiTags.all,
app: [CASES_FEATURE_ID, 'kibana'],
const casesReadAPICapabilities = casesApiTags.read.filter( catalogue: [APP_ID],
(capability) => capability !== GET_CONNECTORS_CONFIGURE_API_TAG cases: {
); create: [APP_ID],
read: [APP_ID],
return { update: [APP_ID],
id: CASES_FEATURE_ID, push: [APP_ID],
name: i18n.translate('xpack.securitySolution.featureRegistry.linkSecuritySolutionCaseTitle', {
defaultMessage: 'Cases',
}),
order: 1100,
category: DEFAULT_APP_CATEGORIES.security,
app: [CASES_FEATURE_ID, 'kibana'],
catalogue: [APP_ID],
cases: [APP_ID],
privileges: {
all: {
api: casesAllAPICapabilities,
app: [CASES_FEATURE_ID, 'kibana'],
catalogue: [APP_ID],
cases: {
create: [APP_ID],
read: [APP_ID],
update: [APP_ID],
},
savedObject: {
all: [...filesSavedObjectTypes],
read: [...filesSavedObjectTypes],
},
ui: casesAllUICapabilities,
}, },
read: { savedObject: {
api: casesReadAPICapabilities, all: [...filesSavedObjectTypes],
app: [CASES_FEATURE_ID, 'kibana'], read: [...filesSavedObjectTypes],
catalogue: [APP_ID],
cases: {
read: [APP_ID],
},
savedObject: {
all: [],
read: [...filesSavedObjectTypes],
},
ui: casesReadUICapabilities,
}, },
ui: casesCapabilities.all,
}, },
}; read: {
}; api: casesApiTags.read,
app: [CASES_FEATURE_ID, 'kibana'],
catalogue: [APP_ID],
cases: {
read: [APP_ID],
},
savedObject: {
all: [],
read: [...filesSavedObjectTypes],
},
ui: casesCapabilities.read,
},
},
});
export const getCasesBaseKibanaSubFeatureIds = (): CasesSubFeatureId[] => [ export const getCasesBaseKibanaSubFeatureIds = (): CasesSubFeatureId[] => [
CasesSubFeatureId.deleteCases, CasesSubFeatureId.deleteCases,
@ -101,18 +79,6 @@ export const getCasesBaseKibanaSubFeatureIds = (): CasesSubFeatureId[] => [
*/ */
export const getCasesAppFeaturesConfig = (): AppFeaturesCasesConfig => ({ export const getCasesAppFeaturesConfig = (): AppFeaturesCasesConfig => ({
[AppFeatureCasesKey.casesConnectors]: { [AppFeatureCasesKey.casesConnectors]: {
privileges: { // TODO: Add cases connector configuration privileges
all: {
api: [GET_CONNECTORS_CONFIGURE_API_TAG], // Add cases connector get connectors API privileges
ui: [CASES_CONNECTORS_CAPABILITY], // Add cases connector UI privileges
cases: {
push: [APP_ID], // Add cases connector push privileges
},
},
read: {
api: [GET_CONNECTORS_CONFIGURE_API_TAG], // Add cases connector get connectors API privileges
ui: [CASES_CONNECTORS_CAPABILITY], // Add cases connector UI privileges
},
},
}, },
}); });

View file

@ -44,30 +44,6 @@ export const noCasesPrivilegesSpace1: Role = {
}, },
}; };
export const noCasesConnectors: Role = {
name: 'no_cases_connectors',
privileges: {
elasticsearch: {
indices: [
{
names: ['*'],
privileges: ['all'],
},
],
},
kibana: [
{
feature: {
testNoCasesConnectorFixture: ['all'],
actions: ['all'],
actionsSimulators: ['all'],
},
spaces: ['*'],
},
],
},
};
export const globalRead: Role = { export const globalRead: Role = {
name: 'global_read', name: 'global_read',
privileges: { privileges: {
@ -377,7 +353,6 @@ export const securitySolutionOnlyAllSpacesRole: Role = {
export const roles = [ export const roles = [
noKibanaPrivileges, noKibanaPrivileges,
noCasesPrivilegesSpace1, noCasesPrivilegesSpace1,
noCasesConnectors,
globalRead, globalRead,
securitySolutionOnlyAll, securitySolutionOnlyAll,
securitySolutionOnlyRead, securitySolutionOnlyRead,

View file

@ -21,7 +21,6 @@ import {
securitySolutionOnlyReadAlerts, securitySolutionOnlyReadAlerts,
securitySolutionOnlyReadNoIndexAlerts, securitySolutionOnlyReadNoIndexAlerts,
securitySolutionOnlyReadDelete, securitySolutionOnlyReadDelete,
noCasesConnectors as noCasesConnectorRole,
} from './roles'; } from './roles';
import { User } from './types'; import { User } from './types';
@ -127,12 +126,6 @@ export const noCasesPrivilegesSpace1: User = {
roles: [noCasesPrivilegesSpace1Role.name], roles: [noCasesPrivilegesSpace1Role.name],
}; };
export const noCasesConnectors: User = {
username: 'no_cases_connectors',
password: 'no_cases_connectors',
roles: [noCasesConnectorRole.name],
};
/** /**
* These users will have access to all spaces. * These users will have access to all spaces.
*/ */
@ -161,5 +154,4 @@ export const users = [
noKibanaPrivileges, noKibanaPrivileges,
noCasesPrivilegesSpace1, noCasesPrivilegesSpace1,
testDisabled, testDisabled,
noCasesConnectors,
]; ];

View file

@ -40,45 +40,6 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
registerRoutes(core, this.log); registerRoutes(core, this.log);
registerCaseFixtureFileKinds(deps.files); registerCaseFixtureFileKinds(deps.files);
/**
* Kibana features
*/
deps.features.registerKibanaFeature({
id: 'testNoCasesConnectorFixture',
name: 'TestNoCasesConnectorFixture',
app: ['kibana'],
category: { id: 'cases-fixtures', label: 'Cases Fixtures' },
cases: ['testNoCasesConnectorFixture'],
privileges: {
all: {
api: [],
app: ['kibana'],
cases: {
create: ['testNoCasesConnectorFixture'],
read: ['testNoCasesConnectorFixture'],
update: ['testNoCasesConnectorFixture'],
},
savedObject: {
all: [],
read: [],
},
ui: [],
},
read: {
app: ['kibana'],
cases: {
read: ['testNoCasesConnectorFixture'],
},
savedObject: {
all: [],
read: [],
},
ui: [],
},
},
});
} }
public start(core: CoreStart, plugins: FixtureStartDeps) {} public start(core: CoreStart, plugins: FixtureStartDeps) {}

View file

@ -31,7 +31,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
cases: ['observabilityFixture'], cases: ['observabilityFixture'],
privileges: { privileges: {
all: { all: {
api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles', 'casesGetConnectorsConfigure'], api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'],
app: ['kibana'], app: ['kibana'],
cases: { cases: {
all: ['observabilityFixture'], all: ['observabilityFixture'],
@ -43,7 +43,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
ui: [], ui: [],
}, },
read: { read: {
api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles', 'casesGetConnectorsConfigure'], api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'],
app: ['kibana'], app: ['kibana'],
cases: { cases: {
read: ['observabilityFixture'], read: ['observabilityFixture'],

View file

@ -39,7 +39,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
cases: ['securitySolutionFixture'], cases: ['securitySolutionFixture'],
privileges: { privileges: {
all: { all: {
api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles', 'casesGetConnectorsConfigure'], api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'],
app: ['kibana'], app: ['kibana'],
cases: { cases: {
create: ['securitySolutionFixture'], create: ['securitySolutionFixture'],
@ -54,7 +54,7 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
ui: [], ui: [],
}, },
read: { read: {
api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles', 'casesGetConnectorsConfigure'], api: ['casesSuggestUserProfiles', 'bulkGetUserProfiles'],
app: ['kibana'], app: ['kibana'],
cases: { cases: {
read: ['securitySolutionFixture'], read: ['securitySolutionFixture'],

View file

@ -6,7 +6,7 @@
*/ */
import { ConnectorTypes } from '@kbn/cases-plugin/common/types/domain'; import { ConnectorTypes } from '@kbn/cases-plugin/common/types/domain';
import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context';
import { postCaseReq } from '../../../../common/lib/mock'; import { postCaseReq } from '../../../../common/lib/mock';
import { import {

View file

@ -54,7 +54,6 @@ import {
} from '../../../../common/lib/api'; } from '../../../../common/lib/api';
import { import {
globalRead, globalRead,
noCasesConnectors,
noKibanaPrivileges, noKibanaPrivileges,
obsOnlyRead, obsOnlyRead,
obsSecRead, obsSecRead,
@ -841,24 +840,6 @@ export default ({ getService }: FtrProviderContext): void => {
expect(theCase.status).to.eql('open'); expect(theCase.status).to.eql('open');
}); });
it('should return 403 when the user does not have access to push', async () => {
const { postedCase } = await createCaseWithConnector({
supertest,
serviceNowSimulatorURL,
actionsRemover,
configureReq: { owner: 'testNoCasesConnectorFixture' },
createCaseReq: { ...getPostCaseRequest(), owner: 'testNoCasesConnectorFixture' },
});
await pushCase({
supertest: supertestWithoutAuth,
caseId: postedCase.id,
connectorId: postedCase.connector.id,
expectedHttpCode: 403,
auth: { user: noCasesConnectors, space: null },
});
});
}); });
}); });
}); });

View file

@ -6,7 +6,7 @@
*/ */
import expect from '@kbn/expect'; import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import { FtrProviderContext } from '../../../../../common/ftr_provider_context';
import { ObjectRemover as ActionsRemover } from '../../../../../alerting_api_integration/common/lib'; import { ObjectRemover as ActionsRemover } from '../../../../../alerting_api_integration/common/lib';
import { import {
@ -20,12 +20,10 @@ import {
getCaseConnectors, getCaseConnectors,
getCasesWebhookConnector, getCasesWebhookConnector,
} from '../../../../common/lib/api'; } from '../../../../common/lib/api';
import { noCasesConnectors } from '../../../../common/lib/authentication/users';
// eslint-disable-next-line import/no-default-export // eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext): void => { export default ({ getService }: FtrProviderContext): void => {
const supertest = getService('supertest'); const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const actionsRemover = new ActionsRemover(supertest); const actionsRemover = new ActionsRemover(supertest);
describe('get_connectors', () => { describe('get_connectors', () => {
@ -186,13 +184,5 @@ export default ({ getService }: FtrProviderContext): void => {
}, },
]); ]);
}); });
it('should return 403 when the user does not have access to the case connectors', async () => {
await getCaseConnectors({
supertest: supertestWithoutAuth,
auth: { user: noCasesConnectors, space: null },
expectedHttpCode: 403,
});
});
}); });
}; };

View file

@ -42,7 +42,6 @@ const permissions = {
update: true, update: true,
delete: true, delete: true,
push: true, push: true,
connectors: true,
}; };
const attachments = [{ type: AttachmentType.user as const, comment: 'test' }]; const attachments = [{ type: AttachmentType.user as const, comment: 'test' }];