Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .buildkite/ftr_configs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ disabled:
- x-pack/test/security_solution_api_integration/config/ess/config.base.ts
- x-pack/test/security_solution_api_integration/config/serverless/config.base.ts
- x-pack/test/security_solution_endpoint/config.base.ts
- x-pack/test/security_solution_endpoint_api_int/config.base.ts

# QA suites that are run out-of-band
- x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js
Expand Down Expand Up @@ -385,6 +386,7 @@ enabled:
- x-pack/test/security_functional/user_profiles.config.ts
- x-pack/test/security_functional/expired_session.config.ts
- x-pack/test/security_solution_endpoint_api_int/config.ts
- x-pack/test/security_solution_endpoint_api_int/serverless.config.ts
- x-pack/test/security_solution_endpoint/endpoint.config.ts
- x-pack/test/security_solution_endpoint/serverless.endpoint.config.ts
- x-pack/test/security_solution_endpoint/integrations.config.ts
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { getDetectionsEngineer } from './detections_engineer';
import { getWithResponseActionsRole } from './with_response_actions_role';
import { getNoResponseActionsRole } from './without_response_actions_role';
import { getWithArtifactReadPrivilegesRole } from './with_artifact_read_privileges_role';

export * from './with_response_actions_role';
export * from './without_response_actions_role';
Expand Down Expand Up @@ -74,6 +75,7 @@ export const ENDPOINT_SECURITY_ROLE_NAMES = Object.freeze({
endpoint_response_actions_access: 'endpoint_response_actions_access',
endpoint_response_actions_no_access: 'endpoint_response_actions_no_access',
endpoint_security_policy_management_read: 'endpoint_security_policy_management_read',
artifact_read_privileges: 'artifact_read_privileges',
});

export const getAllEndpointSecurityRoles = (): EndpointSecurityRoleDefinitions => {
Expand Down Expand Up @@ -135,5 +137,9 @@ export const getAllEndpointSecurityRoles = (): EndpointSecurityRoleDefinitions =
...getEndpointSecurityPolicyManagementReadRole(),
name: 'endpoint_security_policy_management_read',
},
artifact_read_privileges: {
...getWithArtifactReadPrivilegesRole(),
name: 'artifact_read_privileges',
},
};
};
5 changes: 4 additions & 1 deletion x-pack/test/security_solution_endpoint/config.base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ import {
} from '../security_solution_endpoint_api_int/registry';
import type { TargetTags } from './target_tags';

const SUITE_TAGS: Record<string, { include: TargetTags[]; exclude: TargetTags[] }> = {
export const SUITE_TAGS: Record<
'ess' | 'serverless',
{ include: TargetTags[]; exclude: TargetTags[] }
> = {
ess: {
include: ['@ess'],
exclude: ['@skipInEss'],
Expand Down
6 changes: 5 additions & 1 deletion x-pack/test/security_solution_endpoint/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { TimelineTestService } from '../../security_solution_ftr/services/timeli
import { DetectionsTestService } from '../../security_solution_ftr/services/detections';
import { EndpointPolicyTestResourcesProvider } from './endpoint_policy';
import { EndpointArtifactsTestResources } from './endpoint_artifacts';
import { KibanaSupertestWithCertProvider } from './supertest_with_cert';
import {
KibanaSupertestWithCertProvider,
KibanaSupertestWithCertWithoutAuthProvider,
} from './supertest_with_cert';

export const services = {
...xPackFunctionalServices,
Expand All @@ -31,4 +34,5 @@ export const svlServices = {
...services,

supertest: KibanaSupertestWithCertProvider,
supertestWithoutAuth: KibanaSupertestWithCertWithoutAuthProvider,
};
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ export function KibanaSupertestWithCertProvider({ getService }: FtrProviderConte

return supertest.agent(kibanaServerUrl, { ca });
}

export function KibanaSupertestWithCertWithoutAuthProvider({ getService }: FtrProviderContext) {
const config = getService('config');
const kibanaServerUrl = formatUrl({ ...config.get('servers.kibana'), auth: false });
const ca = config.get('servers.kibana').certificateAuthorities;

return supertest.agent(kibanaServerUrl, { ca });
}
49 changes: 40 additions & 9 deletions x-pack/test/security_solution_endpoint/target_tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,44 @@
* 2.0.
*/

export type TargetTags =
| '@ess'
| '@skipInEss'
| '@serverless'
| '@skipInServerless'
| '@brokenInServerless';

export const targetTags = (thisSuite: Mocha.Suite, tags: TargetTags[]) => {
import expect from '@kbn/expect';

const TARGET_TAGS = [
'@ess',
'@skipInEss',
'@serverless',
'@skipInServerless',
'@brokenInServerless',
] as const;

export type TargetTags = typeof TARGET_TAGS[number];

export function targetTags(thisSuite: Mocha.Suite, tags: TargetTags[]) {
// @ts-ignore: _tags is not publicly visible
const existingTags = (thisSuite._tags as string[]) ?? [];
const existingTargetTags = existingTags.filter((tag) => TARGET_TAGS.includes(tag as TargetTags));

if (existingTargetTags.length > 0) {
return expect().fail(`

⚠️ ERROR in \`${targetTags.name}()\`: the passed suite already has target tags.

Suite name: ${thisSuite.title}
Existing tags: ${existingTargetTags.join(', ')}
New tags: ${tags.join(', ')}

💡 This can happen if you call \`${targetTags.name}()\` twice in the same block, or
→ from the inside of an arrow function
→ which is passed to a \`describe()\` block
→ which is somewhere inside \`${thisSuite.title}\`.

☝️ Correct usage:
describe('must receive a regular function', function () {
${targetTags.name}(this, ['@serverless']);
})

`);
}

thisSuite.tags(tags);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
GLOBAL_ARTIFACT_TAG,
} from '@kbn/security-solution-plugin/common/endpoint/service/artifacts';
import { ExceptionsListItemGenerator } from '@kbn/security-solution-plugin/common/endpoint/data_generators/exceptions_list_item_generator';
import { targetTags } from '../../../security_solution_endpoint/target_tags';
import { FtrProviderContext } from '../../ftr_provider_context';
import { PolicyTestResourceInfo } from '../../../security_solution_endpoint/services/endpoint_policy';
import { ArtifactTestData } from '../../../security_solution_endpoint/services/endpoint_artifacts';
Expand All @@ -24,7 +25,9 @@ export default function ({ getService }: FtrProviderContext) {
const endpointPolicyTestResources = getService('endpointPolicyTestResources');
const endpointArtifactTestResources = getService('endpointArtifactTestResources');

describe('Endpoint artifacts (via lists plugin): Blocklists', () => {
describe('Endpoint artifacts (via lists plugin): Blocklists', function () {
targetTags(this, ['@ess', '@serverless']);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just curious - could this have been implemented using this.targetTags()? That could make the implementation a bit cleaner.

I know that this.tag() already exists (or used to - it was used to break up tests into groups).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I agree on that, it would be cleaner. I found some clues about how mocha is decorated in our environment, but couldn't make this work in a short amount of time, so now I'd go with this solution, and maybe return to this later (e.g. on OnWeek)


let fleetEndpointPolicy: PolicyTestResourceInfo;

before(async () => {
Expand Down Expand Up @@ -155,7 +158,7 @@ export default function ({ getService }: FtrProviderContext) {

body.entries[0].field = 'some.invalid.field';
await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.analyst_hunter, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(400)
Expand All @@ -176,7 +179,7 @@ export default function ({ getService }: FtrProviderContext) {
];

await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.analyst_hunter, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(400)
Expand All @@ -197,7 +200,7 @@ export default function ({ getService }: FtrProviderContext) {
];

await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.analyst_hunter, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(400)
Expand All @@ -224,7 +227,7 @@ export default function ({ getService }: FtrProviderContext) {
];

await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.analyst_hunter, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(400)
Expand Down Expand Up @@ -258,7 +261,7 @@ export default function ({ getService }: FtrProviderContext) {
];

await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.analyst_hunter, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(400)
Expand All @@ -272,7 +275,7 @@ export default function ({ getService }: FtrProviderContext) {
body.os_types = ['linux', 'windows'];

await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.analyst_hunter, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(400)
Expand All @@ -297,32 +300,31 @@ export default function ({ getService }: FtrProviderContext) {
for (const blocklistApiCall of [...needsWritePrivilege, ...needsReadPrivilege]) {
it(`should not error on [${blocklistApiCall.method}] - [${blocklistApiCall.info}]`, async () => {
await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.analyst_hunter, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(blocklistApiCall.getBody())
.expect(200);
});
}
});

describe('and user has authorization to read blocklist', () => {
describe('and user has authorization to read blocklist', function () {
targetTags(this, ['@skipInServerless']); // no such role in serverless

for (const blocklistApiCall of [...blocklistApiCalls, ...needsWritePrivilege]) {
it(`should error on [${blocklistApiCall.method}] - [${blocklistApiCall.info}]`, async () => {
await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.artifact_read_role, 'changeme')
.auth(ROLE.artifact_read_privileges, 'changeme')
.set('kbn-xsrf', 'true')
.send(blocklistApiCall.getBody())
.expect(403, {
status_code: 403,
message: 'EndpointArtifactError: Endpoint authorization failure',
});
.expect(403);
});
}

for (const blocklistApiCall of needsReadPrivilege) {
it(`should not error on [${blocklistApiCall.method}] - [${blocklistApiCall.info}]`, async () => {
await supertestWithoutAuth[blocklistApiCall.method](blocklistApiCall.path)
.auth(ROLE.artifact_read_role, 'changeme')
.auth(ROLE.artifact_read_privileges, 'changeme')
.set('kbn-xsrf', 'true')
.send(blocklistApiCall.getBody())
.expect(200);
Expand All @@ -341,10 +343,7 @@ export default function ({ getService }: FtrProviderContext) {
.auth(ROLE.t1_analyst, 'changeme')
.set('kbn-xsrf', 'true')
.send(blocklistApiCall.getBody())
.expect(403, {
status_code: 403,
message: 'EndpointArtifactError: Endpoint authorization failure',
});
.expect(403);
});
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
getImportExceptionsListSchemaMock,
toNdJsonString,
} from '@kbn/lists-plugin/common/schemas/request/import_exceptions_schema.mock';
import { targetTags } from '../../../security_solution_endpoint/target_tags';
import { FtrProviderContext } from '../../ftr_provider_context';
import { PolicyTestResourceInfo } from '../../../security_solution_endpoint/services/endpoint_policy';
import { ArtifactTestData } from '../../../security_solution_endpoint/services/endpoint_artifacts';
Expand All @@ -25,7 +26,9 @@ export default function ({ getService }: FtrProviderContext) {
const endpointPolicyTestResources = getService('endpointPolicyTestResources');
const endpointArtifactTestResources = getService('endpointArtifactTestResources');

describe('Endpoint artifacts (via lists plugin): Event Filters', () => {
describe('Endpoint artifacts (via lists plugin): Event Filters', function () {
targetTags(this, ['@ess', '@serverless']);

let fleetEndpointPolicy: PolicyTestResourceInfo;

before(async () => {
Expand Down Expand Up @@ -182,7 +185,7 @@ export default function ({ getService }: FtrProviderContext) {
const body = eventFilterApiCall.getBody({ os_types: ['linux', 'windows'] });

await supertestWithoutAuth[eventFilterApiCall.method](eventFilterApiCall.path)
.auth(ROLE.endpoint_security_policy_manager, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(400)
Expand All @@ -197,7 +200,7 @@ export default function ({ getService }: FtrProviderContext) {

// Using superuser there as we need custom license for this action
await supertest[eventFilterApiCall.method](eventFilterApiCall.path)
.auth(ROLE.endpoint_security_policy_manager, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(400)
Expand All @@ -210,7 +213,7 @@ export default function ({ getService }: FtrProviderContext) {

// Using superuser here as we need custom license for this action
await supertest[eventFilterApiCall.method](eventFilterApiCall.path)
.auth(ROLE.endpoint_security_policy_manager, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(body)
.expect(200);
Expand All @@ -222,32 +225,31 @@ export default function ({ getService }: FtrProviderContext) {
for (const eventFilterApiCall of [...needsWritePrivilege, ...needsReadPrivilege]) {
it(`should not error on [${eventFilterApiCall.method}] - [${eventFilterApiCall.info}]`, async () => {
await supertestWithoutAuth[eventFilterApiCall.method](eventFilterApiCall.path)
.auth(ROLE.endpoint_security_policy_manager, 'changeme')
.auth(ROLE.endpoint_policy_manager, 'changeme')
.set('kbn-xsrf', 'true')
.send(eventFilterApiCall.getBody())
.expect(200);
});
}
});

describe('and user has authorization to read event filters', () => {
describe('and user has authorization to read event filters', function () {
targetTags(this, ['@skipInServerless']); // no such role in serverless

for (const eventFilterApiCall of [...eventFilterCalls, ...needsWritePrivilege]) {
it(`should error on [${eventFilterApiCall.method}] - [${eventFilterApiCall.info}]`, async () => {
await supertestWithoutAuth[eventFilterApiCall.method](eventFilterApiCall.path)
.auth(ROLE.artifact_read_role, 'changeme')
.auth(ROLE.hunter, 'changeme')
.set('kbn-xsrf', 'true')
.send(eventFilterApiCall.getBody())
.expect(403, {
status_code: 403,
message: 'EndpointArtifactError: Endpoint authorization failure',
});
.expect(403);
});
}

for (const eventFilterApiCall of needsReadPrivilege) {
it(`should not error on [${eventFilterApiCall.method}] - [${eventFilterApiCall.info}]`, async () => {
await supertestWithoutAuth[eventFilterApiCall.method](eventFilterApiCall.path)
.auth(ROLE.artifact_read_role, 'changeme')
.auth(ROLE.hunter, 'changeme')
.set('kbn-xsrf', 'true')
.send(eventFilterApiCall.getBody())
.expect(200);
Expand All @@ -266,10 +268,7 @@ export default function ({ getService }: FtrProviderContext) {
.auth(ROLE.t1_analyst, 'changeme')
.set('kbn-xsrf', 'true')
.send(eventFilterApiCall.getBody())
.expect(403, {
status_code: 403,
message: 'EndpointArtifactError: Endpoint authorization failure',
});
.expect(403);
});
}
});
Expand Down
Loading