mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[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:
parent
1a920d1301
commit
f5fda2ce79
17 changed files with 653 additions and 13 deletions
|
@ -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';
|
||||
|
|
|
@ -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(
|
||||
{
|
||||
|
|
|
@ -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(
|
||||
{
|
||||
|
|
|
@ -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(
|
||||
{
|
||||
|
|
|
@ -65,6 +65,9 @@ export const defineGetComplianceDashboardRoute = (router: CspRouter) =>
|
|||
.get({
|
||||
access: 'internal',
|
||||
path: STATS_ROUTE_PATH,
|
||||
options: {
|
||||
tags: ['access:cloud-security-posture-read'],
|
||||
},
|
||||
})
|
||||
.addVersion(
|
||||
{
|
||||
|
|
|
@ -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(
|
||||
{
|
||||
|
|
|
@ -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',
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
},
|
||||
};
|
||||
}
|
30
x-pack/test/cloud_security_posture_api/routes/index.ts
Normal file
30
x-pack/test/cloud_security_posture_api/routes/index.ts
Normal 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'));
|
||||
});
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
66
x-pack/test/cloud_security_posture_api/routes/status.ts
Normal file
66
x-pack/test/cloud_security_posture_api/routes/status.ts
Normal 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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue