mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Cases][ResponseOps] Splitting out cases privileges (#134860)
* Splitting out cases privs * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * Getting tests working * Fixing import error * Fixing tests * Fixing role to only have delete permissions * Extracting sub feature tests to trial license * Removing deletion user from common tests * Addressing feedback * Fixing tests Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
4b7b363e9c
commit
c4c9c73668
13 changed files with 728 additions and 107 deletions
|
@ -156,6 +156,26 @@ export interface FeatureKibanaPrivileges {
|
|||
* ```
|
||||
*/
|
||||
all?: readonly string[];
|
||||
/**
|
||||
* List of case owners which users should have push access to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* push: ['securitySolution']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
push?: readonly string[];
|
||||
/**
|
||||
* List of case owners which users should have create access to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* create: ['securitySolution']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
create?: readonly string[];
|
||||
/**
|
||||
* List of case owners which users should have read-only access to when granted this privilege.
|
||||
* @example
|
||||
|
@ -166,6 +186,26 @@ export interface FeatureKibanaPrivileges {
|
|||
* ```
|
||||
*/
|
||||
read?: readonly string[];
|
||||
/**
|
||||
* List of case owners which users should have update access to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* update: ['securitySolution']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
update?: readonly string[];
|
||||
/**
|
||||
* List of case owners which users should have delete access to when granted this privilege.
|
||||
* @example
|
||||
* ```ts
|
||||
* {
|
||||
* delete: ['securitySolution']
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
delete?: readonly string[];
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -530,7 +530,11 @@ Array [
|
|||
],
|
||||
"cases": Object {
|
||||
"all": Array [],
|
||||
"create": Array [],
|
||||
"delete": Array [],
|
||||
"push": Array [],
|
||||
"read": Array [],
|
||||
"update": Array [],
|
||||
},
|
||||
"catalogue": Array [
|
||||
"dashboard",
|
||||
|
@ -682,7 +686,11 @@ Array [
|
|||
],
|
||||
"cases": Object {
|
||||
"all": Array [],
|
||||
"create": Array [],
|
||||
"delete": Array [],
|
||||
"push": Array [],
|
||||
"read": Array [],
|
||||
"update": Array [],
|
||||
},
|
||||
"catalogue": Array [
|
||||
"discover",
|
||||
|
@ -893,7 +901,11 @@ Array [
|
|||
],
|
||||
"cases": Object {
|
||||
"all": Array [],
|
||||
"create": Array [],
|
||||
"delete": Array [],
|
||||
"push": Array [],
|
||||
"read": Array [],
|
||||
"update": Array [],
|
||||
},
|
||||
"catalogue": Array [
|
||||
"visualize",
|
||||
|
@ -1026,7 +1038,11 @@ Array [
|
|||
],
|
||||
"cases": Object {
|
||||
"all": Array [],
|
||||
"create": Array [],
|
||||
"delete": Array [],
|
||||
"push": Array [],
|
||||
"read": Array [],
|
||||
"update": Array [],
|
||||
},
|
||||
"catalogue": Array [
|
||||
"dashboard",
|
||||
|
@ -1178,7 +1194,11 @@ Array [
|
|||
],
|
||||
"cases": Object {
|
||||
"all": Array [],
|
||||
"create": Array [],
|
||||
"delete": Array [],
|
||||
"push": Array [],
|
||||
"read": Array [],
|
||||
"update": Array [],
|
||||
},
|
||||
"catalogue": Array [
|
||||
"discover",
|
||||
|
@ -1389,7 +1409,11 @@ Array [
|
|||
],
|
||||
"cases": Object {
|
||||
"all": Array [],
|
||||
"create": Array [],
|
||||
"delete": Array [],
|
||||
"push": Array [],
|
||||
"read": Array [],
|
||||
"update": Array [],
|
||||
},
|
||||
"catalogue": Array [
|
||||
"visualize",
|
||||
|
|
|
@ -72,7 +72,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -137,7 +141,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -201,7 +209,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -267,7 +279,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -303,7 +319,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -360,7 +380,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-sub-type'],
|
||||
create: ['cases-create-sub-type'],
|
||||
read: ['cases-read-sub-type'],
|
||||
update: ['cases-update-sub-type'],
|
||||
delete: ['cases-delete-sub-type'],
|
||||
push: ['cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -402,7 +426,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -465,7 +493,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -522,7 +554,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-sub-type'],
|
||||
create: ['cases-create-sub-type'],
|
||||
read: ['cases-read-sub-type'],
|
||||
update: ['cases-update-sub-type'],
|
||||
delete: ['cases-delete-sub-type'],
|
||||
push: ['cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -564,7 +600,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -627,7 +667,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -685,7 +729,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-sub-type'],
|
||||
create: ['cases-create-sub-type'],
|
||||
read: ['cases-read-sub-type'],
|
||||
update: ['cases-update-sub-type'],
|
||||
delete: ['cases-delete-sub-type'],
|
||||
push: ['cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -730,7 +778,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type', 'cases-all-sub-type'],
|
||||
create: ['cases-create-type', 'cases-create-sub-type'],
|
||||
read: ['cases-read-type', 'cases-read-sub-type'],
|
||||
update: ['cases-update-type', 'cases-update-sub-type'],
|
||||
delete: ['cases-delete-type', 'cases-delete-sub-type'],
|
||||
push: ['cases-push-type', 'cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-action', 'ui-sub-type'],
|
||||
},
|
||||
|
@ -762,6 +814,10 @@ describe('featurePrivilegeIterator', () => {
|
|||
cases: {
|
||||
all: ['cases-all-sub-type'],
|
||||
read: ['cases-read-type', 'cases-read-sub-type'],
|
||||
create: ['cases-create-sub-type'],
|
||||
update: ['cases-update-sub-type'],
|
||||
delete: ['cases-delete-sub-type'],
|
||||
push: ['cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-action', 'ui-sub-type'],
|
||||
},
|
||||
|
@ -799,7 +855,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -899,7 +959,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -929,7 +993,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: [],
|
||||
create: [],
|
||||
read: ['cases-read-type'],
|
||||
update: [],
|
||||
delete: [],
|
||||
push: [],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -965,7 +1033,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -1024,6 +1096,10 @@ describe('featurePrivilegeIterator', () => {
|
|||
cases: {
|
||||
all: ['cases-all-sub-type'],
|
||||
read: ['cases-read-sub-type'],
|
||||
create: ['cases-create-sub-type'],
|
||||
update: ['cases-update-sub-type'],
|
||||
delete: ['cases-delete-sub-type'],
|
||||
push: ['cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -1068,7 +1144,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type', 'cases-all-sub-type'],
|
||||
create: ['cases-create-type', 'cases-create-sub-type'],
|
||||
read: ['cases-read-type', 'cases-read-sub-type'],
|
||||
update: ['cases-update-type', 'cases-update-sub-type'],
|
||||
delete: ['cases-delete-type', 'cases-delete-sub-type'],
|
||||
push: ['cases-push-type', 'cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-action', 'ui-sub-type'],
|
||||
},
|
||||
|
@ -1256,7 +1336,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-sub-type'],
|
||||
create: ['cases-create-sub-type'],
|
||||
read: ['cases-read-sub-type'],
|
||||
update: ['cases-update-sub-type'],
|
||||
delete: ['cases-delete-sub-type'],
|
||||
push: ['cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -1301,7 +1385,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-sub-type'],
|
||||
create: ['cases-create-sub-type'],
|
||||
read: ['cases-read-sub-type'],
|
||||
update: ['cases-update-sub-type'],
|
||||
delete: ['cases-delete-sub-type'],
|
||||
push: ['cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -1332,7 +1420,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-sub-type'],
|
||||
create: ['cases-create-sub-type'],
|
||||
read: ['cases-read-sub-type'],
|
||||
update: ['cases-update-sub-type'],
|
||||
delete: ['cases-delete-sub-type'],
|
||||
push: ['cases-push-sub-type'],
|
||||
},
|
||||
ui: ['ui-sub-type'],
|
||||
},
|
||||
|
@ -1368,7 +1460,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -1454,7 +1550,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: ['cases-all-type'],
|
||||
create: ['cases-create-type'],
|
||||
read: ['cases-read-type'],
|
||||
update: ['cases-update-type'],
|
||||
delete: ['cases-delete-type'],
|
||||
push: ['cases-push-type'],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
@ -1484,7 +1584,11 @@ describe('featurePrivilegeIterator', () => {
|
|||
},
|
||||
cases: {
|
||||
all: [],
|
||||
create: [],
|
||||
read: ['cases-read-type'],
|
||||
update: [],
|
||||
delete: [],
|
||||
push: [],
|
||||
},
|
||||
ui: ['ui-action'],
|
||||
},
|
||||
|
|
|
@ -135,7 +135,20 @@ function mergeWithSubFeatures(
|
|||
|
||||
mergedConfig.cases = {
|
||||
all: mergeArrays(mergedConfig.cases?.all ?? [], subFeaturePrivilege.cases?.all ?? []),
|
||||
create: mergeArrays(
|
||||
mergedConfig.cases?.create ?? [],
|
||||
subFeaturePrivilege.cases?.create ?? []
|
||||
),
|
||||
read: mergeArrays(mergedConfig.cases?.read ?? [], subFeaturePrivilege.cases?.read ?? []),
|
||||
update: mergeArrays(
|
||||
mergedConfig.cases?.update ?? [],
|
||||
subFeaturePrivilege.cases?.update ?? []
|
||||
),
|
||||
delete: mergeArrays(
|
||||
mergedConfig.cases?.delete ?? [],
|
||||
subFeaturePrivilege.cases?.delete ?? []
|
||||
),
|
||||
push: mergeArrays(mergedConfig.cases?.push ?? [], subFeaturePrivilege.cases?.push ?? []),
|
||||
};
|
||||
}
|
||||
return mergedConfig;
|
||||
|
|
|
@ -74,6 +74,17 @@ const appCategorySchema = schema.object({
|
|||
order: schema.maybe(schema.number()),
|
||||
});
|
||||
|
||||
const casesSchemaObject = schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(casesSchema),
|
||||
create: schema.maybe(casesSchema),
|
||||
read: schema.maybe(casesSchema),
|
||||
update: schema.maybe(casesSchema),
|
||||
delete: schema.maybe(casesSchema),
|
||||
push: schema.maybe(casesSchema),
|
||||
})
|
||||
);
|
||||
|
||||
const kibanaPrivilegeSchema = schema.object({
|
||||
excludeFromBasePrivileges: schema.maybe(schema.boolean()),
|
||||
requireAllSpaces: schema.maybe(schema.boolean()),
|
||||
|
@ -98,12 +109,7 @@ const kibanaPrivilegeSchema = schema.object({
|
|||
),
|
||||
})
|
||||
),
|
||||
cases: schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(casesSchema),
|
||||
read: schema.maybe(casesSchema),
|
||||
})
|
||||
),
|
||||
cases: casesSchemaObject,
|
||||
savedObject: schema.object({
|
||||
all: schema.arrayOf(schema.string()),
|
||||
read: schema.arrayOf(schema.string()),
|
||||
|
@ -140,12 +146,7 @@ const kibanaIndependentSubFeaturePrivilegeSchema = schema.object({
|
|||
),
|
||||
})
|
||||
),
|
||||
cases: schema.maybe(
|
||||
schema.object({
|
||||
all: schema.maybe(casesSchema),
|
||||
read: schema.maybe(casesSchema),
|
||||
})
|
||||
),
|
||||
cases: casesSchemaObject,
|
||||
api: schema.maybe(schema.arrayOf(schema.string())),
|
||||
app: schema.maybe(schema.arrayOf(schema.string())),
|
||||
savedObject: schema.object({
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`cases feature_privilege_builder within feature grants all privileges under feature with id observability 1`] = `
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:observability/pushCase",
|
||||
"cases:1.0.0-zeta1:observability/createCase",
|
||||
"cases:1.0.0-zeta1:observability/createComment",
|
||||
"cases:1.0.0-zeta1:observability/createConfiguration",
|
||||
"cases:1.0.0-zeta1:observability/getCase",
|
||||
"cases:1.0.0-zeta1:observability/getComment",
|
||||
"cases:1.0.0-zeta1:observability/getTags",
|
||||
"cases:1.0.0-zeta1:observability/getReporters",
|
||||
"cases:1.0.0-zeta1:observability/getUserActions",
|
||||
"cases:1.0.0-zeta1:observability/findConfigurations",
|
||||
"cases:1.0.0-zeta1:observability/updateCase",
|
||||
"cases:1.0.0-zeta1:observability/updateComment",
|
||||
"cases:1.0.0-zeta1:observability/updateConfiguration",
|
||||
"cases:1.0.0-zeta1:observability/deleteCase",
|
||||
"cases:1.0.0-zeta1:observability/deleteComment",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`cases feature_privilege_builder within feature grants create privileges under feature with id securitySolution 1`] = `
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:securitySolution/createCase",
|
||||
"cases:1.0.0-zeta1:securitySolution/createComment",
|
||||
"cases:1.0.0-zeta1:securitySolution/createConfiguration",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`cases feature_privilege_builder within feature grants delete privileges under feature with id securitySolution 1`] = `
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:securitySolution/deleteCase",
|
||||
"cases:1.0.0-zeta1:securitySolution/deleteComment",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`cases feature_privilege_builder within feature grants push privileges under feature with id obs 1`] = `
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:obs/pushCase",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`cases feature_privilege_builder within feature grants read privileges under feature with id observability 1`] = `
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:observability/getCase",
|
||||
"cases:1.0.0-zeta1:observability/getComment",
|
||||
"cases:1.0.0-zeta1:observability/getTags",
|
||||
"cases:1.0.0-zeta1:observability/getReporters",
|
||||
"cases:1.0.0-zeta1:observability/getUserActions",
|
||||
"cases:1.0.0-zeta1:observability/findConfigurations",
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`cases feature_privilege_builder within feature grants update privileges under feature with id observability 1`] = `
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:observability/updateCase",
|
||||
"cases:1.0.0-zeta1:observability/updateComment",
|
||||
"cases:1.0.0-zeta1:observability/updateConfiguration",
|
||||
]
|
||||
`;
|
|
@ -42,13 +42,20 @@ describe(`cases`, () => {
|
|||
});
|
||||
|
||||
describe(`within feature`, () => {
|
||||
it('grants `read` privileges under feature', () => {
|
||||
it.each([
|
||||
['all', 'observability'],
|
||||
['push', 'obs'],
|
||||
['create', 'securitySolution'],
|
||||
['read', 'observability'],
|
||||
['update', 'observability'],
|
||||
['delete', 'securitySolution'],
|
||||
])('grants %s privileges under feature with id %s', (operation, featureID) => {
|
||||
const actions = new Actions(version);
|
||||
const casesFeaturePrivilege = new FeaturePrivilegeCasesBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
cases: {
|
||||
read: ['observability'],
|
||||
[operation]: [featureID],
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
|
@ -69,73 +76,19 @@ describe(`cases`, () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(casesFeaturePrivilege.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:observability/getCase",
|
||||
"cases:1.0.0-zeta1:observability/getComment",
|
||||
"cases:1.0.0-zeta1:observability/getTags",
|
||||
"cases:1.0.0-zeta1:observability/getReporters",
|
||||
"cases:1.0.0-zeta1:observability/getUserActions",
|
||||
"cases:1.0.0-zeta1:observability/findConfigurations",
|
||||
]
|
||||
`);
|
||||
expect(casesFeaturePrivilege.getActions(privilege, feature)).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('grants `all` privileges under feature', () => {
|
||||
const actions = new Actions(version);
|
||||
const casesFeaturePrivilege = new FeaturePrivilegeCasesBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
cases: {
|
||||
all: ['security'],
|
||||
},
|
||||
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
};
|
||||
|
||||
const feature = new KibanaFeature({
|
||||
id: 'my-feature',
|
||||
name: 'my-feature',
|
||||
app: [],
|
||||
category: { id: 'foo', label: 'foo' },
|
||||
privileges: {
|
||||
all: privilege,
|
||||
read: privilege,
|
||||
},
|
||||
});
|
||||
|
||||
expect(casesFeaturePrivilege.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:security/getCase",
|
||||
"cases:1.0.0-zeta1:security/getComment",
|
||||
"cases:1.0.0-zeta1:security/getTags",
|
||||
"cases:1.0.0-zeta1:security/getReporters",
|
||||
"cases:1.0.0-zeta1:security/getUserActions",
|
||||
"cases:1.0.0-zeta1:security/findConfigurations",
|
||||
"cases:1.0.0-zeta1:security/createCase",
|
||||
"cases:1.0.0-zeta1:security/deleteCase",
|
||||
"cases:1.0.0-zeta1:security/updateCase",
|
||||
"cases:1.0.0-zeta1:security/pushCase",
|
||||
"cases:1.0.0-zeta1:security/createComment",
|
||||
"cases:1.0.0-zeta1:security/deleteComment",
|
||||
"cases:1.0.0-zeta1:security/updateComment",
|
||||
"cases:1.0.0-zeta1:security/createConfiguration",
|
||||
"cases:1.0.0-zeta1:security/updateConfiguration",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
||||
it('grants both `all` and `read` privileges under feature', () => {
|
||||
it('grants all privileges under feature', () => {
|
||||
const actions = new Actions(version);
|
||||
const casesFeaturePrivilege = new FeaturePrivilegeCasesBuilder(actions);
|
||||
|
||||
const privilege: FeatureKibanaPrivileges = {
|
||||
cases: {
|
||||
all: ['security'],
|
||||
create: ['security'],
|
||||
update: ['obs'],
|
||||
delete: ['security'],
|
||||
read: ['obs'],
|
||||
},
|
||||
|
||||
|
@ -159,27 +112,30 @@ describe(`cases`, () => {
|
|||
|
||||
expect(casesFeaturePrivilege.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:security/pushCase",
|
||||
"cases:1.0.0-zeta1:security/createCase",
|
||||
"cases:1.0.0-zeta1:security/createComment",
|
||||
"cases:1.0.0-zeta1:security/createConfiguration",
|
||||
"cases:1.0.0-zeta1:security/getCase",
|
||||
"cases:1.0.0-zeta1:security/getComment",
|
||||
"cases:1.0.0-zeta1:security/getTags",
|
||||
"cases:1.0.0-zeta1:security/getReporters",
|
||||
"cases:1.0.0-zeta1:security/getUserActions",
|
||||
"cases:1.0.0-zeta1:security/findConfigurations",
|
||||
"cases:1.0.0-zeta1:security/createCase",
|
||||
"cases:1.0.0-zeta1:security/deleteCase",
|
||||
"cases:1.0.0-zeta1:security/updateCase",
|
||||
"cases:1.0.0-zeta1:security/pushCase",
|
||||
"cases:1.0.0-zeta1:security/createComment",
|
||||
"cases:1.0.0-zeta1:security/deleteComment",
|
||||
"cases:1.0.0-zeta1:security/updateComment",
|
||||
"cases:1.0.0-zeta1:security/createConfiguration",
|
||||
"cases:1.0.0-zeta1:security/updateConfiguration",
|
||||
"cases:1.0.0-zeta1:security/deleteCase",
|
||||
"cases:1.0.0-zeta1:security/deleteComment",
|
||||
"cases:1.0.0-zeta1:obs/getCase",
|
||||
"cases:1.0.0-zeta1:obs/getComment",
|
||||
"cases:1.0.0-zeta1:obs/getTags",
|
||||
"cases:1.0.0-zeta1:obs/getReporters",
|
||||
"cases:1.0.0-zeta1:obs/getUserActions",
|
||||
"cases:1.0.0-zeta1:obs/findConfigurations",
|
||||
"cases:1.0.0-zeta1:obs/updateCase",
|
||||
"cases:1.0.0-zeta1:obs/updateComment",
|
||||
"cases:1.0.0-zeta1:obs/updateConfiguration",
|
||||
]
|
||||
`);
|
||||
});
|
||||
|
@ -214,36 +170,36 @@ describe(`cases`, () => {
|
|||
|
||||
expect(casesFeaturePrivilege.getActions(privilege, feature)).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
"cases:1.0.0-zeta1:security/pushCase",
|
||||
"cases:1.0.0-zeta1:security/createCase",
|
||||
"cases:1.0.0-zeta1:security/createComment",
|
||||
"cases:1.0.0-zeta1:security/createConfiguration",
|
||||
"cases:1.0.0-zeta1:security/getCase",
|
||||
"cases:1.0.0-zeta1:security/getComment",
|
||||
"cases:1.0.0-zeta1:security/getTags",
|
||||
"cases:1.0.0-zeta1:security/getReporters",
|
||||
"cases:1.0.0-zeta1:security/getUserActions",
|
||||
"cases:1.0.0-zeta1:security/findConfigurations",
|
||||
"cases:1.0.0-zeta1:security/createCase",
|
||||
"cases:1.0.0-zeta1:security/deleteCase",
|
||||
"cases:1.0.0-zeta1:security/updateCase",
|
||||
"cases:1.0.0-zeta1:security/pushCase",
|
||||
"cases:1.0.0-zeta1:security/createComment",
|
||||
"cases:1.0.0-zeta1:security/deleteComment",
|
||||
"cases:1.0.0-zeta1:security/updateComment",
|
||||
"cases:1.0.0-zeta1:security/createConfiguration",
|
||||
"cases:1.0.0-zeta1:security/updateConfiguration",
|
||||
"cases:1.0.0-zeta1:security/deleteCase",
|
||||
"cases:1.0.0-zeta1:security/deleteComment",
|
||||
"cases:1.0.0-zeta1:other-security/pushCase",
|
||||
"cases:1.0.0-zeta1:other-security/createCase",
|
||||
"cases:1.0.0-zeta1:other-security/createComment",
|
||||
"cases:1.0.0-zeta1:other-security/createConfiguration",
|
||||
"cases:1.0.0-zeta1:other-security/getCase",
|
||||
"cases:1.0.0-zeta1:other-security/getComment",
|
||||
"cases:1.0.0-zeta1:other-security/getTags",
|
||||
"cases:1.0.0-zeta1:other-security/getReporters",
|
||||
"cases:1.0.0-zeta1:other-security/getUserActions",
|
||||
"cases:1.0.0-zeta1:other-security/findConfigurations",
|
||||
"cases:1.0.0-zeta1:other-security/createCase",
|
||||
"cases:1.0.0-zeta1:other-security/deleteCase",
|
||||
"cases:1.0.0-zeta1:other-security/updateCase",
|
||||
"cases:1.0.0-zeta1:other-security/pushCase",
|
||||
"cases:1.0.0-zeta1:other-security/createComment",
|
||||
"cases:1.0.0-zeta1:other-security/deleteComment",
|
||||
"cases:1.0.0-zeta1:other-security/updateComment",
|
||||
"cases:1.0.0-zeta1:other-security/createConfiguration",
|
||||
"cases:1.0.0-zeta1:other-security/updateConfiguration",
|
||||
"cases:1.0.0-zeta1:other-security/deleteCase",
|
||||
"cases:1.0.0-zeta1:other-security/deleteComment",
|
||||
"cases:1.0.0-zeta1:obs/getCase",
|
||||
"cases:1.0.0-zeta1:obs/getComment",
|
||||
"cases:1.0.0-zeta1:obs/getTags",
|
||||
|
|
|
@ -15,6 +15,9 @@ export type CasesSupportedOperations = typeof allOperations[number];
|
|||
|
||||
// if you add a value here you'll likely also need to make changes here:
|
||||
// x-pack/plugins/cases/server/authorization/index.ts
|
||||
|
||||
const pushOperations = ['pushCase'] as const;
|
||||
const createOperations = ['createCase', 'createComment', 'createConfiguration'] as const;
|
||||
const readOperations = [
|
||||
'getCase',
|
||||
'getComment',
|
||||
|
@ -23,19 +26,15 @@ const readOperations = [
|
|||
'getUserActions',
|
||||
'findConfigurations',
|
||||
] as const;
|
||||
|
||||
const writeOperations = [
|
||||
'createCase',
|
||||
'deleteCase',
|
||||
'updateCase',
|
||||
'pushCase',
|
||||
'createComment',
|
||||
'deleteComment',
|
||||
'updateComment',
|
||||
'createConfiguration',
|
||||
'updateConfiguration',
|
||||
const updateOperations = ['updateCase', 'updateComment', 'updateConfiguration'] as const;
|
||||
const deleteOperations = ['deleteCase', 'deleteComment'] as const;
|
||||
const allOperations = [
|
||||
...pushOperations,
|
||||
...createOperations,
|
||||
...readOperations,
|
||||
...updateOperations,
|
||||
...deleteOperations,
|
||||
] as const;
|
||||
const allOperations = [...readOperations, ...writeOperations] as const;
|
||||
|
||||
export class FeaturePrivilegeCasesBuilder extends BaseFeaturePrivilegeBuilder {
|
||||
public getActions(
|
||||
|
@ -44,7 +43,7 @@ export class FeaturePrivilegeCasesBuilder extends BaseFeaturePrivilegeBuilder {
|
|||
): string[] {
|
||||
const getCasesPrivilege = (
|
||||
operations: readonly CasesSupportedOperations[],
|
||||
owners: readonly string[]
|
||||
owners: readonly string[] = []
|
||||
) => {
|
||||
return owners.flatMap((owner) =>
|
||||
operations.map((operation) => this.actions.cases.get(owner, operation))
|
||||
|
@ -52,8 +51,12 @@ export class FeaturePrivilegeCasesBuilder extends BaseFeaturePrivilegeBuilder {
|
|||
};
|
||||
|
||||
return uniq([
|
||||
...getCasesPrivilege(allOperations, privilegeDefinition.cases?.all ?? []),
|
||||
...getCasesPrivilege(readOperations, privilegeDefinition.cases?.read ?? []),
|
||||
...getCasesPrivilege(allOperations, privilegeDefinition.cases?.all),
|
||||
...getCasesPrivilege(pushOperations, privilegeDefinition.cases?.push),
|
||||
...getCasesPrivilege(createOperations, privilegeDefinition.cases?.create),
|
||||
...getCasesPrivilege(readOperations, privilegeDefinition.cases?.read),
|
||||
...getCasesPrivilege(updateOperations, privilegeDefinition.cases?.update),
|
||||
...getCasesPrivilege(deleteOperations, privilegeDefinition.cases?.delete),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,10 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
all: {
|
||||
app: ['kibana'],
|
||||
cases: {
|
||||
all: ['securitySolutionFixture'],
|
||||
create: ['securitySolutionFixture'],
|
||||
read: ['securitySolutionFixture'],
|
||||
update: ['securitySolutionFixture'],
|
||||
push: ['securitySolutionFixture'],
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
|
@ -53,6 +56,31 @@ export class FixturePlugin implements Plugin<void, void, FixtureSetupDeps, Fixtu
|
|||
ui: [],
|
||||
},
|
||||
},
|
||||
subFeatures: [
|
||||
{
|
||||
name: 'Custom privileges',
|
||||
privilegeGroups: [
|
||||
{
|
||||
groupType: 'independent',
|
||||
privileges: [
|
||||
{
|
||||
name: 'Delete',
|
||||
id: 'cases_delete',
|
||||
includeIn: 'all',
|
||||
cases: {
|
||||
delete: ['securitySolutionFixture'],
|
||||
},
|
||||
savedObject: {
|
||||
all: [],
|
||||
read: [],
|
||||
},
|
||||
ui: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
features.registerKibanaFeature({
|
||||
|
|
|
@ -95,6 +95,54 @@ export const securitySolutionOnlyAll: Role = {
|
|||
},
|
||||
};
|
||||
|
||||
export const securitySolutionOnlyDelete: Role = {
|
||||
name: 'sec_only_delete',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
names: ['*'],
|
||||
privileges: ['all'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
securitySolutionFixture: ['cases_delete'],
|
||||
actions: ['all'],
|
||||
actionsSimulators: ['all'],
|
||||
},
|
||||
spaces: ['space1'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const securitySolutionOnlyNoDelete: Role = {
|
||||
name: 'sec_only_no_delete',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
names: ['*'],
|
||||
privileges: ['all'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
securitySolutionFixture: ['minimal_all'],
|
||||
actions: ['all'],
|
||||
actionsSimulators: ['all'],
|
||||
},
|
||||
spaces: ['space1'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const securitySolutionOnlyRead: Role = {
|
||||
name: 'sec_only_read',
|
||||
privileges: {
|
||||
|
@ -172,6 +220,8 @@ export const roles = [
|
|||
globalRead,
|
||||
securitySolutionOnlyAll,
|
||||
securitySolutionOnlyRead,
|
||||
securitySolutionOnlyDelete,
|
||||
securitySolutionOnlyNoDelete,
|
||||
observabilityOnlyAll,
|
||||
observabilityOnlyRead,
|
||||
testDisabledPluginAll,
|
||||
|
|
|
@ -17,6 +17,8 @@ import {
|
|||
observabilityOnlyAllSpacesAll,
|
||||
observabilityOnlyReadSpacesAll,
|
||||
testDisabledPluginAll,
|
||||
securitySolutionOnlyDelete,
|
||||
securitySolutionOnlyNoDelete,
|
||||
} from './roles';
|
||||
import { User } from './types';
|
||||
|
||||
|
@ -38,6 +40,18 @@ export const secOnly: User = {
|
|||
roles: [securitySolutionOnlyAll.name],
|
||||
};
|
||||
|
||||
export const secOnlyDelete: User = {
|
||||
username: 'sec_only_delete',
|
||||
password: 'sec_only_delete',
|
||||
roles: [securitySolutionOnlyDelete.name],
|
||||
};
|
||||
|
||||
export const secOnlyNoDelete: User = {
|
||||
username: 'sec_only_no_delete',
|
||||
password: 'sec_only_no_delete',
|
||||
roles: [securitySolutionOnlyNoDelete.name],
|
||||
};
|
||||
|
||||
export const secOnlyRead: User = {
|
||||
username: 'sec_only_read',
|
||||
password: 'sec_only_read',
|
||||
|
@ -84,6 +98,8 @@ export const users = [
|
|||
superUser,
|
||||
secOnly,
|
||||
secOnlyRead,
|
||||
secOnlyDelete,
|
||||
secOnlyNoDelete,
|
||||
obsOnly,
|
||||
obsOnlyRead,
|
||||
obsSec,
|
||||
|
|
|
@ -0,0 +1,323 @@
|
|||
/*
|
||||
* 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 { CASES_URL } from '@kbn/cases-plugin/common';
|
||||
import { FtrProviderContext } from '../../../common/ftr_provider_context';
|
||||
|
||||
import { getPostCaseRequest, postCommentUserReq } from '../../../common/lib/mock';
|
||||
import {
|
||||
deleteAllCaseItems,
|
||||
createCase,
|
||||
deleteCases,
|
||||
createComment,
|
||||
getCase,
|
||||
superUserSpace1Auth,
|
||||
findCases,
|
||||
deleteComment,
|
||||
getSpaceUrlPrefix,
|
||||
updateComment,
|
||||
deleteAllComments,
|
||||
} from '../../../common/lib/utils';
|
||||
import {
|
||||
superUser,
|
||||
secOnlyDelete,
|
||||
secOnlyNoDelete,
|
||||
} from '../../../common/lib/authentication/users';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default ({ getService }: FtrProviderContext): void => {
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
const es = getService('es');
|
||||
|
||||
describe('user with deletion sub privilege', () => {
|
||||
afterEach(async () => {
|
||||
await deleteAllCaseItems(es);
|
||||
});
|
||||
|
||||
describe('successful operations', () => {
|
||||
it(`should delete a case`, async () => {
|
||||
const postedCase = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{
|
||||
user: superUser,
|
||||
space: 'space1',
|
||||
}
|
||||
);
|
||||
|
||||
await deleteCases({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseIDs: [postedCase.id],
|
||||
expectedHttpCode: 204,
|
||||
auth: { user: secOnlyDelete, space: 'space1' },
|
||||
});
|
||||
});
|
||||
|
||||
it(`should delete a case with a comment`, async () => {
|
||||
const secCase = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{ user: superUser, space: 'space1' }
|
||||
);
|
||||
|
||||
await createComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: secCase.id,
|
||||
params: postCommentUserReq,
|
||||
auth: { user: superUser, space: 'space1' },
|
||||
});
|
||||
|
||||
await deleteCases({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseIDs: [secCase.id],
|
||||
expectedHttpCode: 204,
|
||||
auth: { user: secOnlyDelete, space: 'space1' },
|
||||
});
|
||||
});
|
||||
|
||||
it(`should delete a comment from the appropriate owner`, async () => {
|
||||
const secCase = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{ user: superUser, space: 'space1' }
|
||||
);
|
||||
|
||||
const commentResp = await createComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: secCase.id,
|
||||
params: postCommentUserReq,
|
||||
auth: { user: superUser, space: 'space1' },
|
||||
});
|
||||
|
||||
await deleteComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: secCase.id,
|
||||
commentId: commentResp.comments![0].id,
|
||||
auth: { user: secOnlyDelete, space: 'space1' },
|
||||
});
|
||||
});
|
||||
|
||||
it(`should delete all comments from a case`, async () => {
|
||||
const secCase = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{ user: superUser, space: 'space1' }
|
||||
);
|
||||
|
||||
await createComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: secCase.id,
|
||||
params: postCommentUserReq,
|
||||
auth: { user: superUser, space: 'space1' },
|
||||
});
|
||||
|
||||
await createComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: secCase.id,
|
||||
params: postCommentUserReq,
|
||||
auth: { user: superUser, space: 'space1' },
|
||||
});
|
||||
|
||||
await deleteAllComments({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: secCase.id,
|
||||
auth: { user: secOnlyDelete, space: 'space1' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('failed operations', () => {
|
||||
describe('cases', () => {
|
||||
for (const scenario of [{ user: secOnlyDelete, space: 'space1' }]) {
|
||||
it(`User ${scenario.user.username} with role(s) ${scenario.user.roles.join()} and space ${
|
||||
scenario.space
|
||||
} - should NOT read a case`, async () => {
|
||||
// super user creates a case at the appropriate space
|
||||
await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{
|
||||
user: superUser,
|
||||
space: scenario.space,
|
||||
}
|
||||
);
|
||||
|
||||
// user should not be able to read cases at the appropriate space
|
||||
await findCases({
|
||||
supertest: supertestWithoutAuth,
|
||||
auth: {
|
||||
user: scenario.user,
|
||||
space: scenario.space,
|
||||
},
|
||||
expectedHttpCode: 403,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('should not get a case when the user does not have read permissions', async () => {
|
||||
const newCase = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{
|
||||
user: superUser,
|
||||
space: 'space1',
|
||||
}
|
||||
);
|
||||
|
||||
for (const user of [secOnlyDelete]) {
|
||||
await getCase({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: newCase.id,
|
||||
expectedHttpCode: 403,
|
||||
auth: { user, space: 'space1' },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it(`should not create a case`, async () => {
|
||||
await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
403,
|
||||
{
|
||||
user: secOnlyDelete,
|
||||
space: 'space1',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it(`should create a case but not delete a case`, async () => {
|
||||
const caseInfo = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{
|
||||
user: secOnlyNoDelete,
|
||||
space: 'space1',
|
||||
}
|
||||
);
|
||||
|
||||
await deleteCases({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseIDs: [caseInfo.id],
|
||||
expectedHttpCode: 403,
|
||||
auth: { user: secOnlyNoDelete, space: 'space1' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('comments', () => {
|
||||
for (const scenario of [{ user: secOnlyDelete, space: 'space1' }]) {
|
||||
it(`User ${scenario.user.username} with role(s) ${scenario.user.roles.join()} and space ${
|
||||
scenario.space
|
||||
} - should NOT read a comment`, async () => {
|
||||
// super user creates a case and comment in the appropriate space
|
||||
const caseInfo = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{ user: superUser, space: scenario.space }
|
||||
);
|
||||
|
||||
await createComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
auth: { user: superUser, space: scenario.space },
|
||||
params: { ...postCommentUserReq, owner: 'securitySolutionFixture' },
|
||||
caseId: caseInfo.id,
|
||||
});
|
||||
|
||||
// user should not be able to read comments
|
||||
await supertestWithoutAuth
|
||||
.get(`${getSpaceUrlPrefix(scenario.space)}${CASES_URL}/${caseInfo.id}/comments/_find`)
|
||||
.auth(scenario.user.username, scenario.user.password)
|
||||
.expect(403);
|
||||
});
|
||||
}
|
||||
|
||||
it('should NOT update a comment', async () => {
|
||||
const postedCase = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
superUserSpace1Auth
|
||||
);
|
||||
|
||||
const patchedCase = await createComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: postedCase.id,
|
||||
params: postCommentUserReq,
|
||||
auth: superUserSpace1Auth,
|
||||
});
|
||||
|
||||
const newComment = 'Well I decided to update my comment. So what? Deal with it.';
|
||||
await updateComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: postedCase.id,
|
||||
req: {
|
||||
...postCommentUserReq,
|
||||
id: patchedCase.comments![0].id,
|
||||
version: patchedCase.comments![0].version,
|
||||
comment: newComment,
|
||||
},
|
||||
auth: { user: secOnlyDelete, space: 'space1' },
|
||||
expectedHttpCode: 403,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not create a comment', async () => {
|
||||
const postedCase = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
superUserSpace1Auth
|
||||
);
|
||||
|
||||
await createComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: postedCase.id,
|
||||
params: postCommentUserReq,
|
||||
auth: { user: secOnlyDelete, space: 'space1' },
|
||||
expectedHttpCode: 403,
|
||||
});
|
||||
});
|
||||
|
||||
it(`should create a comment but not delete a comment`, async () => {
|
||||
const caseInfo = await createCase(
|
||||
supertestWithoutAuth,
|
||||
getPostCaseRequest({ owner: 'securitySolutionFixture' }),
|
||||
200,
|
||||
{
|
||||
user: secOnlyNoDelete,
|
||||
space: 'space1',
|
||||
}
|
||||
);
|
||||
|
||||
const commentResp = await createComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: caseInfo.id,
|
||||
params: postCommentUserReq,
|
||||
auth: { user: secOnlyNoDelete, space: 'space1' },
|
||||
});
|
||||
|
||||
await deleteComment({
|
||||
supertest: supertestWithoutAuth,
|
||||
caseId: caseInfo.id,
|
||||
commentId: commentResp.comments![0].id,
|
||||
auth: { user: secOnlyNoDelete, space: 'space1' },
|
||||
expectedHttpCode: 403,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
|
@ -23,6 +23,8 @@ export default ({ loadTestFile, getService }: FtrProviderContext): void => {
|
|||
loadTestFile(require.resolve('./cases/push_case'));
|
||||
loadTestFile(require.resolve('./cases/user_actions/get_all_user_actions'));
|
||||
loadTestFile(require.resolve('./configure'));
|
||||
// sub privileges are only available with a license above basic
|
||||
loadTestFile(require.resolve('./delete_sub_privilege'));
|
||||
|
||||
// Common
|
||||
loadTestFile(require.resolve('../common'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue