Skip to content

Commit

Permalink
[7.x] [Security Solutions][Detection Engine] Unskips tests after ES p…
Browse files Browse the repository at this point in the history
…romotion and adds deleteUserRole utility (#90533) (#90847)

* [Security Solutions][Detection Engine] Unskips tests after ES promotion and adds deleteUserRole utility (#90533)

## Summary

Unskips tests after a ES promotion and adds a delete user role utility.

Ref:
#90229
#88302

Removes one `any` from the utils by switching to using `ProvidedType`

Before:
<img width="558" alt="Screen Shot 2021-02-05 at 2 45 37 PM" src="https://user-images.githubusercontent.com/1151048/107098890-8dce5b80-67cd-11eb-8f6e-51f83eef4647.png">

After:
<img width="513" alt="Screen Shot 2021-02-05 at 4 13 23 PM" src="https://user-images.githubusercontent.com/1151048/107098898-9161e280-67cd-11eb-8085-a5220938834e.png">

Turns out that return types on overloaded functions aren't easy fwiw and will fall on the bottom one which in this case looked to be `any` which we don't want:
microsoft/TypeScript#24275 (comment)

### Checklist

- [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios

# Conflicts:
#	x-pack/test/detection_engine_api_integration/security_and_spaces/tests/create_index.ts
#	x-pack/test/detection_engine_api_integration/security_and_spaces/tests/delete_signals_migrations.ts

* Fixes test failure as the permissions are true for 7.x -> 7.12 compared to false for 7.11
  • Loading branch information
FrankHassanabad authored Feb 10, 2021
1 parent bd5bbfc commit 6563963
Show file tree
Hide file tree
Showing 8 changed files with 132 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import { assertUnreachable } from '../../../../plugins/security_solution/common/utility_types';
import { FtrProviderContext } from '../../common/ftr_provider_context';
import {
t1AnalystUser,
t2AnalystUser,
Expand All @@ -26,10 +27,9 @@ import {
} from '../../../../plugins/security_solution/server/lib/detection_engine/scripts/roles_users';

import { ROLES } from '../../../../plugins/security_solution/common/test';
import { FtrProviderContext } from '../../common/ftr_provider_context';

export const createUserAndRole = async (
securityService: ReturnType<FtrProviderContext['getService']>,
getService: FtrProviderContext['getService'],
role: ROLES
): Promise<void> => {
switch (role) {
Expand All @@ -38,32 +38,47 @@ export const createUserAndRole = async (
ROLES.detections_admin,
detectionsAdminRole,
detectionsAdminUser,
securityService
getService
);
case ROLES.t1_analyst:
return postRoleAndUser(ROLES.t1_analyst, t1AnalystRole, t1AnalystUser, securityService);
return postRoleAndUser(ROLES.t1_analyst, t1AnalystRole, t1AnalystUser, getService);
case ROLES.t2_analyst:
return postRoleAndUser(ROLES.t2_analyst, t2AnalystRole, t2AnalystUser, securityService);
return postRoleAndUser(ROLES.t2_analyst, t2AnalystRole, t2AnalystUser, getService);
case ROLES.hunter:
return postRoleAndUser(ROLES.hunter, hunterRole, hunterUser, securityService);
return postRoleAndUser(ROLES.hunter, hunterRole, hunterUser, getService);
case ROLES.rule_author:
return postRoleAndUser(ROLES.rule_author, ruleAuthorRole, ruleAuthorUser, securityService);
return postRoleAndUser(ROLES.rule_author, ruleAuthorRole, ruleAuthorUser, getService);
case ROLES.soc_manager:
return postRoleAndUser(ROLES.soc_manager, socManagerRole, socManagerUser, securityService);
return postRoleAndUser(ROLES.soc_manager, socManagerRole, socManagerUser, getService);
case ROLES.platform_engineer:
return postRoleAndUser(
ROLES.platform_engineer,
platformEngineerRole,
platformEngineerUser,
securityService
getService
);
case ROLES.reader:
return postRoleAndUser(ROLES.reader, readerRole, readerUser, securityService);
return postRoleAndUser(ROLES.reader, readerRole, readerUser, getService);
default:
return assertUnreachable(role);
}
};

/**
* Given a roleName and security service this will delete the roleName
* and user
* @param roleName The user and role to delete with the same name
* @param securityService The security service
*/
export const deleteUserAndRole = async (
getService: FtrProviderContext['getService'],
roleName: ROLES
): Promise<void> => {
const securityService = getService('security');
await securityService.user.delete(roleName);
await securityService.role.delete(roleName);
};

interface UserInterface {
password: string;
roles: string[];
Expand Down Expand Up @@ -95,8 +110,9 @@ export const postRoleAndUser = async (
roleName: string,
role: RoleInterface,
user: UserInterface,
securityService: ReturnType<FtrProviderContext['getService']>
) => {
getService: FtrProviderContext['getService']
): Promise<void> => {
const securityService = getService('security');
await securityService.role.create(roleName, {
kibana: role.kibana,
elasticsearch: role.elasticsearch,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,14 @@ import {
import { FtrProviderContext } from '../../common/ftr_provider_context';
import { deleteSignalsIndex } from '../../utils';
import { ROLES } from '../../../../plugins/security_solution/common/test';
import { createUserAndRole } from '../roles_users_utils';
import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils';

// eslint-disable-next-line import/no-default-export
export default ({ getService }: FtrProviderContext) => {
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const security = getService('security');

// FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/90229
describe.skip('create_index', () => {
describe('create_index', () => {
afterEach(async () => {
await deleteSignalsIndex(supertest);
});
Expand Down Expand Up @@ -66,8 +64,13 @@ export default ({ getService }: FtrProviderContext) => {

describe('t1_analyst', () => {
const role = ROLES.t1_analyst;

beforeEach(async () => {
await createUserAndRole(security, role);
await createUserAndRole(getService, role);
});

afterEach(async () => {
await deleteUserAndRole(getService, role);
});

it('should return a 404 when the signal index has never been created', async () => {
Expand All @@ -88,7 +91,7 @@ export default ({ getService }: FtrProviderContext) => {
.expect(403);
expect(body).to.eql({
message:
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [t1_analyst]',
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [t1_analyst], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]',
status_code: 403,
});
});
Expand All @@ -111,8 +114,13 @@ export default ({ getService }: FtrProviderContext) => {

describe('t2_analyst', () => {
const role = ROLES.t2_analyst;

beforeEach(async () => {
await createUserAndRole(security, role);
await createUserAndRole(getService, role);
});

afterEach(async () => {
await deleteUserAndRole(getService, role);
});

it('should return a 404 when the signal index has never been created', async () => {
Expand All @@ -133,7 +141,7 @@ export default ({ getService }: FtrProviderContext) => {
.expect(403);
expect(body).to.eql({
message:
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [t2_analyst]',
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [t2_analyst], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]',
status_code: 403,
});
});
Expand All @@ -156,8 +164,13 @@ export default ({ getService }: FtrProviderContext) => {

describe('detections_admin', () => {
const role = ROLES.detections_admin;

beforeEach(async () => {
await createUserAndRole(security, role);
await createUserAndRole(getService, role);
});

afterEach(async () => {
await deleteUserAndRole(getService, role);
});

it('should return a 404 when the signal index has never been created', async () => {
Expand Down Expand Up @@ -201,8 +214,13 @@ export default ({ getService }: FtrProviderContext) => {

describe('soc_manager', () => {
const role = ROLES.soc_manager;

beforeEach(async () => {
await createUserAndRole(security, role);
await createUserAndRole(getService, role);
});

afterEach(async () => {
await deleteUserAndRole(getService, role);
});

it('should return a 404 when the signal index has never been created', async () => {
Expand All @@ -223,7 +241,7 @@ export default ({ getService }: FtrProviderContext) => {
.expect(403);
expect(body).to.eql({
message:
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [soc_manager]',
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [soc_manager], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]',
status_code: 403,
});
});
Expand All @@ -246,8 +264,13 @@ export default ({ getService }: FtrProviderContext) => {

describe('hunter', () => {
const role = ROLES.hunter;

beforeEach(async () => {
await createUserAndRole(security, role);
await createUserAndRole(getService, role);
});

afterEach(async () => {
await deleteUserAndRole(getService, role);
});

it('should return a 404 when the signal index has never been created', async () => {
Expand All @@ -268,7 +291,7 @@ export default ({ getService }: FtrProviderContext) => {
.expect(403);
expect(body).to.eql({
message:
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [hunter]',
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [hunter], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]',
status_code: 403,
});
});
Expand All @@ -291,8 +314,13 @@ export default ({ getService }: FtrProviderContext) => {

describe('platform_engineer', () => {
const role = ROLES.platform_engineer;

beforeEach(async () => {
await createUserAndRole(security, role);
await createUserAndRole(getService, role);
});

afterEach(async () => {
await deleteUserAndRole(getService, role);
});

it('should return a 404 when the signal index has never been created', async () => {
Expand Down Expand Up @@ -336,8 +364,13 @@ export default ({ getService }: FtrProviderContext) => {

describe('reader', () => {
const role = ROLES.reader;

beforeEach(async () => {
await createUserAndRole(security, role);
await createUserAndRole(getService, role);
});

afterEach(async () => {
await deleteUserAndRole(getService, role);
});

it('should return a 404 when the signal index has never been created', async () => {
Expand All @@ -358,7 +391,7 @@ export default ({ getService }: FtrProviderContext) => {
.expect(403);
expect(body).to.eql({
message:
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [reader]',
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [reader], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]',
status_code: 403,
});
});
Expand All @@ -381,8 +414,13 @@ export default ({ getService }: FtrProviderContext) => {

describe('rule_author', () => {
const role = ROLES.rule_author;

beforeEach(async () => {
await createUserAndRole(security, role);
await createUserAndRole(getService, role);
});

afterEach(async () => {
await deleteUserAndRole(getService, role);
});

it('should return a 404 when the signal index has never been created', async () => {
Expand All @@ -403,7 +441,7 @@ export default ({ getService }: FtrProviderContext) => {
.expect(403);
expect(body).to.eql({
message:
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [rule_author]',
'security_exception: action [cluster:admin/ilm/get] is unauthorized for user [rule_author], this action is granted by the cluster privileges [read_ilm,manage_ilm,manage,all]',
status_code: 403,
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
getIndexNameFromLoad,
waitForIndexToPopulate,
} from '../../utils';
import { createUserAndRole } from '../roles_users_utils';
import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils';

interface CreateResponse {
index: string;
Expand All @@ -34,7 +34,6 @@ export default ({ getService }: FtrProviderContext): void => {
const es = getService('es');
const esArchiver = getService('esArchiver');
const kbnClient = getService('kibanaServer');
const security = getService('security');
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');

Expand Down Expand Up @@ -173,14 +172,16 @@ export default ({ getService }: FtrProviderContext): void => {
});

it('rejects the request if the user does not have sufficient privileges', async () => {
await createUserAndRole(security, ROLES.t1_analyst);
await createUserAndRole(getService, ROLES.t1_analyst);

await supertestWithoutAuth
.post(DETECTION_ENGINE_SIGNALS_MIGRATION_URL)
.set('kbn-xsrf', 'true')
.auth(ROLES.t1_analyst, 'changeme')
.send({ index: [legacySignalsIndexName] })
.expect(400);

await deleteUserAndRole(getService, ROLES.t1_analyst);
});
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,10 @@ interface FinalizeResponse extends CreateResponse {
export default ({ getService }: FtrProviderContext): void => {
const es = getService('es');
const esArchiver = getService('esArchiver');
const security = getService('security');
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');

// FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/90229
describe.skip('deleting signals migrations', () => {
describe('deleting signals migrations', () => {
let outdatedSignalsIndexName: string;
let createdMigration: CreateResponse;
let finalizedMigration: FinalizeResponse;
Expand Down Expand Up @@ -105,7 +103,7 @@ export default ({ getService }: FtrProviderContext): void => {
});

it('rejects the request if the user does not have sufficient privileges', async () => {
await createUserAndRole(security, ROLES.t1_analyst);
await createUserAndRole(getService, ROLES.t1_analyst);

const { body } = await supertestWithoutAuth
.delete(DETECTION_ENGINE_SIGNALS_MIGRATION_URL)
Expand All @@ -117,10 +115,11 @@ export default ({ getService }: FtrProviderContext): void => {
const deletedMigration = body.migrations[0];

expect(deletedMigration.id).to.eql(createdMigration.migration_id);
expect(deletedMigration.error.status_code).to.eql(403);
expect(deletedMigration.error.message).to.contain(
'security_exception: action [indices:admin/settings/update] is unauthorized for user [t1_analyst]'
);
expect(deletedMigration.error).to.eql({
message:
'security_exception: action [indices:admin/settings/update] is unauthorized for user [t1_analyst] on indices [], this action is granted by the index privileges [manage,all]',
status_code: 403,
});
});
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
getIndexNameFromLoad,
waitFor,
} from '../../utils';
import { createUserAndRole } from '../roles_users_utils';
import { createUserAndRole, deleteUserAndRole } from '../roles_users_utils';

interface StatusResponse {
index: string;
Expand All @@ -44,12 +44,10 @@ interface FinalizeResponse {
export default ({ getService }: FtrProviderContext): void => {
const esArchiver = getService('esArchiver');
const kbnClient = getService('kibanaServer');
const security = getService('security');
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');

// FAILING ES PROMOTION: https://github.com/elastic/kibana/issues/88302
describe.skip('Finalizing signals migrations', () => {
describe('Finalizing signals migrations', () => {
let legacySignalsIndexName: string;
let outdatedSignalsIndexName: string;
let createdMigrations: CreateResponse[];
Expand Down Expand Up @@ -234,7 +232,7 @@ export default ({ getService }: FtrProviderContext): void => {
});

it('rejects the request if the user does not have sufficient privileges', async () => {
await createUserAndRole(security, ROLES.t1_analyst);
await createUserAndRole(getService, ROLES.t1_analyst);

const { body } = await supertestWithoutAuth
.post(DETECTION_ENGINE_SIGNALS_FINALIZE_MIGRATION_URL)
Expand All @@ -249,9 +247,11 @@ export default ({ getService }: FtrProviderContext): void => {
expect(finalizeResponse.completed).not.to.eql(true);
expect(finalizeResponse.error).to.eql({
message:
'security_exception: action [cluster:monitor/task/get] is unauthorized for user [t1_analyst]',
'security_exception: action [cluster:monitor/task/get] is unauthorized for user [t1_analyst], this action is granted by the cluster privileges [monitor,manage,all]',
status_code: 403,
});

await deleteUserAndRole(getService, ROLES.t1_analyst);
});
});
};
Loading

0 comments on commit 6563963

Please sign in to comment.