[Cloud Security] Adding Auth check on API (#186937)

## Summary

This PR addresses the issue where currently only some of our API does
Auth check. All of our API should be doing this. Furthermore we are
adding new API FTR to cover this scenario as well

Notes:
Currently Benchmark related API FTR is blocked by
https://github.com/elastic/kibana/issues/188059
This commit is contained in:
Rickyanto Ang 2024-07-12 14:39:59 -07:00 committed by GitHub
parent 1a920d1301
commit f5fda2ce79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 653 additions and 13 deletions

View file

@ -75,6 +75,8 @@ export const DATA_VIEW_INDEX_PATTERN = 'logs-*';
export const SECURITY_DEFAULT_DATA_VIEW_ID = 'security-solution-default';
export const ALERTS_INDEX_PATTERN = '.alerts-security.alerts-*';
export const CSP_INGEST_TIMESTAMP_PIPELINE = 'cloud_security_posture_add_ingest_timestamp_pipeline';
export const CSP_LATEST_FINDINGS_INGEST_TIMESTAMP_PIPELINE =
'cloud_security_posture_latest_index_add_ingest_timestamp_pipeline';

View file

@ -44,6 +44,9 @@ export const defineBulkActionCspBenchmarkRulesRoute = (router: CspRouter) =>
.post({
access: 'internal',
path: CSP_BENCHMARK_RULES_BULK_ACTION_ROUTE_PATH,
options: {
tags: ['access:cloud-security-posture-read'],
},
})
.addVersion(
{

View file

@ -29,6 +29,9 @@ export const defineFindCspBenchmarkRuleRoute = (router: CspRouter) =>
.get({
access: 'internal',
path: FIND_CSP_BENCHMARK_RULE_ROUTE_PATH,
options: {
tags: ['access:cloud-security-posture-read'],
},
})
.addVersion(
{

View file

@ -16,6 +16,9 @@ export const defineGetCspBenchmarkRulesStatesRoute = (router: CspRouter) =>
.get({
access: 'internal',
path: CSP_GET_BENCHMARK_RULES_STATE_ROUTE_PATH,
options: {
tags: ['access:cloud-security-posture-read'],
},
})
.addVersion(
{

View file

@ -65,6 +65,9 @@ export const defineGetComplianceDashboardRoute = (router: CspRouter) =>
.get({
access: 'internal',
path: STATS_ROUTE_PATH,
options: {
tags: ['access:cloud-security-posture-read'],
},
})
.addVersion(
{

View file

@ -57,6 +57,9 @@ export const defineGetDetectionEngineAlertsStatus = (router: CspRouter) =>
.get({
access: 'internal',
path: GET_DETECTION_RULE_ALERTS_STATUS_PATH,
options: {
tags: ['access:cloud-security-posture-read'],
},
})
.addVersion(
{

View file

@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { resolve } from 'path';
import type { FtrConfigProviderContext } from '@kbn/test';
import { CLOUD_SECURITY_PLUGIN_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants';
@ -15,14 +15,7 @@ export default async function ({ readConfigFile }: FtrConfigProviderContext) {
return {
...xpackFunctionalConfig.getAll(),
testFiles: [
require.resolve('./telemetry/telemetry.ts'),
require.resolve('./routes/vulnerabilities_dashboard.ts'),
require.resolve('./routes/stats.ts'),
require.resolve('./routes/csp_benchmark_rules_bulk_update.ts'),
require.resolve('./routes/csp_benchmark_rules_get_states.ts'),
require.resolve('./routes/benchmarks.ts'),
],
testFiles: [resolve(__dirname, './routes')],
junit: {
reportName: 'X-Pack Cloud Security Posture API Tests',
},

View file

@ -17,18 +17,20 @@ import expect from '@kbn/expect';
import Chance from 'chance';
import { CspBenchmarkRule } from '@kbn/cloud-security-posture-plugin/common/types/latest';
import { FtrProviderContext } from '../ftr_provider_context';
import { CspSecurityCommonProvider } from './helper/user_roles_utilites';
const chance = new Chance();
// eslint-disable-next-line import/no-default-export
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const retry = getService('retry');
const es = getService('es');
const kibanaServer = getService('kibanaServer');
const supertest = getService('supertest');
const log = getService('log');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const cspSecurity = CspSecurityCommonProvider(providerContext);
const getCspBenchmarkRules = async (benchmarkId: string): Promise<CspBenchmarkRule[]> => {
let cspBenchmarkRules: CspBenchmarkRule[] = [];
@ -263,5 +265,57 @@ export default function (providerContext: FtrProviderContext) {
expect(scoreAfterMute.score.postureScore).to.equal(0);
});
});
describe('Get Benchmark API', async () => {
beforeEach(async () => {
await index.removeFindings();
await kibanaServer.savedObjects.clean({
types: ['cloud-security-posture-settings'],
});
await waitForPluginInitialized();
});
it('Calling Benchmark API as User with no read access to Security', async () => {
const benchmark = 'cis_aws';
const benchmarkRules = await getCspBenchmarkRules(benchmark);
const cspmFinding1 = getMockFinding(benchmarkRules[0], 'passed');
await index.addFindings([cspmFinding1]);
const { body: benchmarksResult } = await supertestWithoutAuth
.get('/internal/cloud_security_posture/benchmarks')
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_no_read_user',
cspSecurity.getPasswordForUser('role_security_no_read_user')
);
expect(benchmarksResult.statusCode).to.equal(403);
});
// Blocked by https://github.com/elastic/kibana/issues/188059
it.skip('Calling Benchmark API as User with read access to Security', async () => {
const benchmark = 'cis_aws';
const benchmarkRules = await getCspBenchmarkRules(benchmark);
const cspmFinding1 = getMockFinding(benchmarkRules[0], 'passed');
await index.addFindings([cspmFinding1]);
const { status } = await supertestWithoutAuth
.get('/internal/cloud_security_posture/benchmarks')
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_read_user',
cspSecurity.getPasswordForUser('role_security_read_user')
);
expect(status).to.equal(200);
});
});
});
}

View file

@ -21,13 +21,17 @@ import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-plugin/common
// eslint-disable @kbn/imports/no_boundary_crossing
import { generateBenchmarkRuleTags } from '@kbn/cloud-security-posture-plugin/common/utils/detection_rules';
import type { FtrProviderContext } from '../ftr_provider_context';
import { CspSecurityCommonProvider } from './helper/user_roles_utilites';
// eslint-disable-next-line import/no-default-export
export default function ({ getService }: FtrProviderContext) {
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const retry = getService('retry');
const supertest = getService('supertest');
const log = getService('log');
const kibanaServer = getService('kibanaServer');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const cspSecurity = CspSecurityCommonProvider(providerContext);
const generateRuleKey = (rule: CspBenchmarkRule): string => {
return `${rule.metadata.benchmark.id};${rule.metadata.benchmark.version};${rule.metadata.benchmark.rule_number}`;
@ -447,5 +451,68 @@ export default function ({ getService }: FtrProviderContext) {
expect(body.error).to.eql('Bad Request');
expect(body.statusCode).to.eql(400);
});
it('users without read privileges on cloud security should not be able to mute', async () => {
const rule1 = await getRandomCspBenchmarkRule();
const rule2 = await getRandomCspBenchmarkRule();
const { status } = await supertestWithoutAuth
.post(`/internal/cloud_security_posture/rules/_bulk_action`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_no_read_user',
cspSecurity.getPasswordForUser('role_security_no_read_user')
)
.send({
action: 'mute',
rules: [
{
benchmark_id: rule1.metadata.benchmark.id,
benchmark_version: rule1.metadata.benchmark.version,
rule_number: rule1.metadata.benchmark.rule_number || '',
rule_id: rule1.metadata.id,
},
{
benchmark_id: rule2.metadata.benchmark.id,
benchmark_version: rule2.metadata.benchmark.version,
rule_number: rule2.metadata.benchmark.rule_number || '',
rule_id: rule2.metadata.id,
},
],
});
expect(status).to.be(403);
});
// Blocked by https://github.com/elastic/kibana/issues/188059
it.skip('users with read privileges on cloud security should be able to mute', async () => {
const rule1 = await getRandomCspBenchmarkRule();
const rule2 = await getRandomCspBenchmarkRule();
const { status } = await supertestWithoutAuth
.post(`/internal/cloud_security_posture/rules/_bulk_action`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.set('kbn-xsrf', 'xxxx')
.auth('role_security_read_user', cspSecurity.getPasswordForUser('role_security_read_user'))
.send({
action: 'mute',
rules: [
{
benchmark_id: rule1.metadata.benchmark.id,
benchmark_version: rule1.metadata.benchmark.version,
rule_number: rule1.metadata.benchmark.rule_number || '',
rule_id: rule1.metadata.id,
},
{
benchmark_id: rule2.metadata.benchmark.id,
benchmark_version: rule2.metadata.benchmark.version,
rule_number: rule2.metadata.benchmark.rule_number || '',
rule_id: rule2.metadata.id,
},
],
});
expect(status).to.be(200);
});
});
}

View file

@ -15,13 +15,17 @@ import {
import { CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE } from '@kbn/cloud-security-posture-plugin/common/constants';
import type { CspBenchmarkRule } from '@kbn/cloud-security-posture-plugin/common/types/latest';
import type { FtrProviderContext } from '../ftr_provider_context';
import { CspSecurityCommonProvider } from './helper/user_roles_utilites';
// eslint-disable-next-line import/no-default-export
export default function ({ getService }: FtrProviderContext) {
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const retry = getService('retry');
const supertest = getService('supertest');
const log = getService('log');
const kibanaServer = getService('kibanaServer');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const cspSecurity = CspSecurityCommonProvider(providerContext);
const generateRuleKey = (rule: CspBenchmarkRule): string => {
return `${rule.metadata.benchmark.id};${rule.metadata.benchmark.version};${rule.metadata.benchmark.rule_number}`;
@ -160,5 +164,28 @@ export default function ({ getService }: FtrProviderContext) {
expectExpect(body).toEqual({});
});
// Blocked by https://github.com/elastic/kibana/issues/188059
it.skip('GET rules states API with user with read access', async () => {
const { status } = await supertestWithoutAuth
.get(`/internal/cloud_security_posture/rules/_get_states?tags=CIS`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.set('kbn-xsrf', 'xxxx')
.auth('role_security_read_user', cspSecurity.getPasswordForUser('role_security_read_use'));
expect(status).to.be(200);
});
it('GET rules states API API with user without read access', async () => {
const { status } = await supertestWithoutAuth
.get(`/internal/cloud_security_posture/rules/_get_states`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_no_read_user',
cspSecurity.getPasswordForUser('role_security_no_read_user')
);
expect(status).to.be(403);
});
});
}

View file

@ -0,0 +1,70 @@
/*
* 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
import { CspSecurityCommonProvider } from './helper/user_roles_utilites';
// eslint-disable-next-line import/no-default-export
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const retry = getService('retry');
const supertest = getService('supertest');
const log = getService('log');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const cspSecurity = CspSecurityCommonProvider(providerContext);
/**
* required before indexing findings
*/
const waitForPluginInitialized = (): Promise<void> =>
retry.try(async () => {
log.debug('Check CSP plugin is initialized');
const response = await supertest
.get('/internal/cloud_security_posture/status?check=init')
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.expect(200);
expect(response.body).to.eql({ isPluginInitialized: true });
log.debug('CSP plugin is initialized');
});
describe('/internal/cloud_security_posture/detection_engine_rules/alerts/_status', () => {
describe('GET detection_engine_rules API with user that has specific access', async () => {
before(async () => {
await waitForPluginInitialized();
});
it('GET detection_engine_rules API with user with read access', async () => {
const { status } = await supertestWithoutAuth
.get(
'/internal/cloud_security_posture/detection_engine_rules/alerts/_status?tags=["CIS"]'
)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_read_user_alerts',
cspSecurity.getPasswordForUser('role_security_read_user_alerts')
);
expect(status).to.be(200);
});
it('GET detection_engine_rules API with user without read access', async () => {
const { status } = await supertestWithoutAuth
.get(
'/internal/cloud_security_posture/detection_engine_rules/alerts/_status?tags=["CIS"]'
)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_no_read_user_alerts',
cspSecurity.getPasswordForUser('role_security_no_read_user_alerts')
);
expect(status).to.be(403);
});
});
});
}

View file

@ -0,0 +1,15 @@
/*
* 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 { CspSecurityCommonProvider } from './user_roles_utilites';
export const cloudSecurityPosturePageObjects = {
cspSecurity: CspSecurityCommonProvider,
};
export const pageObjects = {
...cloudSecurityPosturePageObjects,
};

View file

@ -0,0 +1,201 @@
/*
* 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 {
LATEST_FINDINGS_INDEX_PATTERN,
BENCHMARK_SCORE_INDEX_PATTERN,
LATEST_VULNERABILITIES_INDEX_PATTERN,
ALERTS_INDEX_PATTERN,
FINDINGS_INDEX_PATTERN,
} from '@kbn/cloud-security-posture-plugin/common/constants';
import type { FtrProviderContext } from '../../ftr_provider_context';
const alertsSecurityUserIndices = [
{
names: [FINDINGS_INDEX_PATTERN],
privileges: ['read'],
},
{
names: [LATEST_FINDINGS_INDEX_PATTERN],
privileges: ['read'],
},
{
names: [BENCHMARK_SCORE_INDEX_PATTERN],
privileges: ['read'],
},
{
names: [LATEST_VULNERABILITIES_INDEX_PATTERN],
privileges: ['all'],
},
{
names: [ALERTS_INDEX_PATTERN],
privileges: ['all'],
},
];
const securityUserIndinces = [
{
names: [FINDINGS_INDEX_PATTERN],
privileges: ['read'],
},
{
names: [LATEST_FINDINGS_INDEX_PATTERN],
privileges: ['read'],
},
{
names: [BENCHMARK_SCORE_INDEX_PATTERN],
privileges: ['read'],
},
{
names: [LATEST_VULNERABILITIES_INDEX_PATTERN],
privileges: ['all'],
},
];
export function CspSecurityCommonProvider(providerContext: FtrProviderContext) {
const { getService } = providerContext;
const security = getService('security');
const roles = [
{
name: 'role_security_no_read',
elasticsearch: {
indices: securityUserIndinces,
},
kibana: [
{
base: [],
feature: {
fleet: ['all'],
fleetv2: ['all'],
savedObjectsManagement: ['all'],
},
spaces: ['*'],
},
],
},
{
name: 'role_security_read',
elasticsearch: {
indices: securityUserIndinces,
},
kibana: [
{
base: [],
feature: {
siem: ['read'],
fleet: ['all'],
fleetv2: ['all'],
savedObjectsManagement: ['all'],
},
spaces: ['*'],
},
],
},
{
name: 'role_security_read_alerts',
elasticsearch: {
indices: alertsSecurityUserIndices,
},
kibana: [
{
base: [],
feature: {
siem: ['read'],
fleet: ['all'],
fleetv2: ['all'],
},
spaces: ['*'],
},
],
},
{
name: 'role_security_no_read_alerts',
elasticsearch: {
indices: alertsSecurityUserIndices,
},
kibana: [
{
base: [],
feature: {
fleet: ['all'],
fleetv2: ['all'],
},
spaces: ['*'],
},
],
},
];
const users = [
{
name: 'role_security_read_user',
full_name: 'security read privilege user',
password: 'test123',
roles: ['role_security_read'],
},
{
name: 'role_security_read_user_alerts',
full_name: 'user with 0 security privilege for',
password: 'csp123',
roles: ['role_security_read_alerts'],
},
{
name: 'role_security_no_read_user',
full_name: 'user with 0 security privilege',
password: 'csp123',
roles: ['role_security_no_read'],
},
{
name: 'role_security_no_read_user_alerts',
full_name: 'user with 0 security privilege for',
password: 'csp123',
roles: ['role_security_no_read_alerts'],
},
];
return {
async createRoles() {
for (const role of roles) {
await security.role.create(role.name, {
elasticsearch: role.elasticsearch,
kibana: role.kibana,
});
}
},
async createUsers() {
for (const user of users) {
await security.user.create(user.name, {
password: user.password,
roles: user.roles,
full_name: user.full_name,
});
}
},
async cleanRoles() {
for (const role of roles) {
await security.role.delete(role.name);
}
},
async cleanUsers() {
for (const user of users) {
await security.user.delete(user.name);
}
},
getPasswordForUser(user: string): string {
const userConfig = users.find((u) => u.name === user);
if (userConfig === undefined) {
throw new Error(`Can't log in user ${user} - not defined`);
}
return userConfig.password;
},
};
}

View file

@ -0,0 +1,30 @@
/*
* 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 { FtrProviderContext } from '../ftr_provider_context';
import { CspSecurityCommonProvider } from './helper/user_roles_utilites';
// eslint-disable-next-line import/no-default-export
export default function (providerContext: FtrProviderContext) {
const { loadTestFile } = providerContext;
const cspSecurity = CspSecurityCommonProvider(providerContext);
describe('Cloud Security Posture', function () {
before(async () => {
await cspSecurity.createRoles();
await cspSecurity.createUsers();
});
loadTestFile(require.resolve('../telemetry/telemetry.ts'));
loadTestFile(require.resolve('./vulnerabilities_dashboard.ts'));
loadTestFile(require.resolve('./stats.ts'));
loadTestFile(require.resolve('./csp_benchmark_rules_bulk_update.ts'));
loadTestFile(require.resolve('./csp_benchmark_rules_get_states.ts'));
loadTestFile(require.resolve('./benchmarks.ts'));
loadTestFile(require.resolve('./status.ts'));
loadTestFile(require.resolve('./get_detection_engine_alerts_count_by_rule_tags'));
});
}

View file

@ -26,6 +26,7 @@ import {
cspmComplianceDashboardDataMockV2,
} from './mocks/benchmark_score_mock';
import { findingsMockData } from './mocks/findings_mock';
import { CspSecurityCommonProvider } from './helper/user_roles_utilites';
const removeRealtimeCalculatedFields = (trends: PostureTrend[]) => {
return trends.map((trend: PostureTrend) => {
@ -61,6 +62,8 @@ export default function (providerContext: FtrProviderContext) {
const es = getService('es');
const supertest = getService('supertest');
const log = getService('log');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const cspSecurity = CspSecurityCommonProvider(providerContext);
/**
* required before indexing findings
@ -295,5 +298,75 @@ export default function (providerContext: FtrProviderContext) {
}).to.eql(kspmComplianceDashboardDataMockV2);
});
});
describe('GET stats API with user that has specific access', async () => {
beforeEach(async () => {
await index.removeFindings();
await index.removeScores();
await waitForPluginInitialized();
});
it('GET stats API V1 with user with read access', async () => {
await index.addScores(getBenchmarkScoreMockData('cspm', true));
await index.addScores(getBenchmarkScoreMockData('cspm', false));
await index.addFindings([findingsMockData[1]]);
const { status } = await supertestWithoutAuth
.get(`/internal/cloud_security_posture/stats/cspm`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_read_user',
cspSecurity.getPasswordForUser('role_security_read_user')
);
expect(status).to.be(200);
});
it('GET stats API V1 with user with read access', async () => {
await index.addScores(getBenchmarkScoreMockData('cspm', true));
await index.addScores(getBenchmarkScoreMockData('cspm', false));
await index.addFindings([findingsMockData[1]]);
const { status } = await supertestWithoutAuth
.get(`/internal/cloud_security_posture/stats/cspm`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_read_user',
cspSecurity.getPasswordForUser('role_security_read_user')
);
expect(status).to.be(200);
});
it('GET stats API V2 with user with read access', async () => {
await index.addScores(getBenchmarkScoreMockData('cspm', true));
await index.addScores(getBenchmarkScoreMockData('cspm', false));
await index.addFindings([findingsMockData[1]]);
const { status } = await supertestWithoutAuth
.get(`/internal/cloud_security_posture/stats/cspm`)
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_read_user',
cspSecurity.getPasswordForUser('role_security_read_user')
);
expect(status).to.be(200);
});
it('GET stats API V2 with user without read access', async () => {
await index.addScores(getBenchmarkScoreMockData('kspm', true));
await index.addScores(getBenchmarkScoreMockData('kspm', false));
await index.addFindings([findingsMockData[0]]);
const { status } = await supertestWithoutAuth
.get(`/internal/cloud_security_posture/stats/kspm`)
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_no_read_user',
cspSecurity.getPasswordForUser('role_security_no_read_user')
);
expect(status).to.be(403);
});
});
});
}

View file

@ -0,0 +1,66 @@
/*
* 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 { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common';
import expect from '@kbn/expect';
import { FtrProviderContext } from '../ftr_provider_context';
import { CspSecurityCommonProvider } from './helper/user_roles_utilites';
// eslint-disable-next-line import/no-default-export
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const retry = getService('retry');
const supertest = getService('supertest');
const log = getService('log');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const cspSecurity = CspSecurityCommonProvider(providerContext);
/**
* required before indexing findings
*/
const waitForPluginInitialized = (): Promise<void> =>
retry.try(async () => {
log.debug('Check CSP plugin is initialized');
const response = await supertest
.get('/internal/cloud_security_posture/status?check=init')
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.expect(200);
expect(response.body).to.eql({ isPluginInitialized: true });
log.debug('CSP plugin is initialized');
});
describe('GET /internal/cloud_security_posture/status', () => {
describe('GET status API with user that has specific access', async () => {
before(async () => {
await waitForPluginInitialized();
});
it('GET stats API with user with read access', async () => {
const { status } = await supertestWithoutAuth
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_read_user',
cspSecurity.getPasswordForUser('role_security_read_user')
);
expect(status).to.be(200);
});
it('GET status API with user without read access', async () => {
const { status } = await supertestWithoutAuth
.get(`/internal/cloud_security_posture/status`)
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_no_read_user',
cspSecurity.getPasswordForUser('role_security_no_read_user')
);
expect(status).to.be(403);
});
});
});
}

View file

@ -13,6 +13,7 @@ import {
vulnerabilitiesLatestMock,
scoresVulnerabilitiesMock,
} from './mocks/vulnerabilities_latest_mock';
import { CspSecurityCommonProvider } from './helper/user_roles_utilites';
export interface CnvmStatistics {
criticalCount?: number;
@ -106,11 +107,14 @@ const removeRealtimeCalculatedFields = (
};
// eslint-disable-next-line import/no-default-export
export default function ({ getService }: FtrProviderContext) {
export default function (providerContext: FtrProviderContext) {
const { getService } = providerContext;
const retry = getService('retry');
const es = getService('es');
const supertest = getService('supertest');
const log = getService('log');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const cspSecurity = CspSecurityCommonProvider(providerContext);
/**
* required before indexing findings
@ -304,5 +308,28 @@ export default function ({ getService }: FtrProviderContext) {
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.expect(500);
});
it('GET vulnerabilities dashboard API with users with read access to cloud security posture', async () => {
const { status } = await supertestWithoutAuth
.get('/internal/cloud_security_posture/vulnerabilities_dashboard')
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.auth('role_security_read_user', cspSecurity.getPasswordForUser('role_security_read_user'));
expect(status).to.be(200);
});
it('GET vulnerabilities dashboard API with users without read access to cloud security posture', async () => {
const { status } = await supertestWithoutAuth
.get('/internal/cloud_security_posture/vulnerabilities_dashboard')
.set(ELASTIC_HTTP_VERSION_HEADER, '1')
.set('kbn-xsrf', 'xxxx')
.auth(
'role_security_no_read_user',
cspSecurity.getPasswordForUser('role_security_no_read_user')
);
expect(status).to.be(403);
});
});
}