mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Routes and E2E tests for kubernetes_security plugin (#133266)
* aggregate and count routes added for kubernetes_security plugins. includes FTR e2e tests. some e2e tests also created for session view plugin. * naming fixes Co-authored-by: mitodrummer <karlgodard@elastic.co>
This commit is contained in:
parent
deb0598c2d
commit
40b1cb95a5
27 changed files with 213302 additions and 70 deletions
|
@ -189,6 +189,7 @@ enabled:
|
|||
- x-pack/test/functional/config_security_basic.ts
|
||||
- x-pack/test/functional/config.ccs.ts
|
||||
- x-pack/test/functional/config.firefox.js
|
||||
- x-pack/test/kubernetes_security/basic/config.ts
|
||||
- x-pack/test/licensing_plugin/config.public.ts
|
||||
- x-pack/test/licensing_plugin/config.ts
|
||||
- x-pack/test/lists_api_integration/security_and_spaces/config.ts
|
||||
|
@ -235,6 +236,7 @@ enabled:
|
|||
- x-pack/test/security_functional/saml.config.ts
|
||||
- x-pack/test/security_solution_endpoint_api_int/config.ts
|
||||
- x-pack/test/security_solution_endpoint/config.ts
|
||||
- x-pack/test/session_view/basic/config.ts
|
||||
- x-pack/test/spaces_api_integration/security_and_spaces/config_basic.ts
|
||||
- x-pack/test/spaces_api_integration/security_and_spaces/config_trial.ts
|
||||
- x-pack/test/spaces_api_integration/spaces_only/config.ts
|
||||
|
|
|
@ -6,3 +6,11 @@
|
|||
*/
|
||||
|
||||
export const KUBERNETES_PATH = '/kubernetes' as const;
|
||||
|
||||
export const AGGREGATE_ROUTE = '/internal/kubernetes_security/aggregate';
|
||||
export const COUNT_ROUTE = '/internal/kubernetes_security/count';
|
||||
export const AGGREGATE_PAGE_SIZE = 10;
|
||||
|
||||
// so, bucket sort can only page through what we request at the top level agg, which means there is a ceiling to how many aggs we can page through.
|
||||
// we should also test this approach at scale.
|
||||
export const AGGREGATE_MAX_BUCKETS = 2000;
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
"requiredPlugins": [
|
||||
"data",
|
||||
"timelines",
|
||||
"ruleRegistry"
|
||||
"ruleRegistry",
|
||||
"sessionView"
|
||||
],
|
||||
"requiredBundles": [],
|
||||
"server": true,
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 { schema } from '@kbn/config-schema';
|
||||
import type { ElasticsearchClient } from '@kbn/core/server';
|
||||
import { IRouter } from '@kbn/core/server';
|
||||
import { PROCESS_EVENTS_INDEX } from '@kbn/session-view-plugin/common/constants';
|
||||
import {
|
||||
AGGREGATE_ROUTE,
|
||||
AGGREGATE_PAGE_SIZE,
|
||||
AGGREGATE_MAX_BUCKETS,
|
||||
} from '../../common/constants';
|
||||
|
||||
export const registerAggregateRoute = (router: IRouter) => {
|
||||
router.get(
|
||||
{
|
||||
path: AGGREGATE_ROUTE,
|
||||
validate: {
|
||||
query: schema.object({
|
||||
query: schema.string(),
|
||||
groupBy: schema.string(),
|
||||
page: schema.number(),
|
||||
index: schema.maybe(schema.string()),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const client = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const { query, groupBy, page, index } = request.query;
|
||||
|
||||
try {
|
||||
const body = await doSearch(client, query, groupBy, page, index);
|
||||
|
||||
return response.ok({ body });
|
||||
} catch (err) {
|
||||
return response.badRequest(err.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const doSearch = async (
|
||||
client: ElasticsearchClient,
|
||||
query: string,
|
||||
groupBy: string,
|
||||
page: number, // zero based
|
||||
index?: string
|
||||
) => {
|
||||
const queryDSL = JSON.parse(query);
|
||||
|
||||
const search = await client.search({
|
||||
index: [index || PROCESS_EVENTS_INDEX],
|
||||
body: {
|
||||
query: queryDSL,
|
||||
size: 0,
|
||||
aggs: {
|
||||
custom_agg: {
|
||||
terms: {
|
||||
field: groupBy,
|
||||
size: AGGREGATE_MAX_BUCKETS,
|
||||
},
|
||||
aggs: {
|
||||
bucket_sort: {
|
||||
bucket_sort: {
|
||||
sort: [{ _key: { order: 'asc' } }], // defaulting to alphabetic sort
|
||||
size: AGGREGATE_PAGE_SIZE,
|
||||
from: AGGREGATE_PAGE_SIZE * page,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const agg: any = search.aggregations?.custom_agg;
|
||||
|
||||
return agg?.buckets || [];
|
||||
};
|
66
x-pack/plugins/kubernetes_security/server/routes/count.ts
Normal file
66
x-pack/plugins/kubernetes_security/server/routes/count.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 { schema } from '@kbn/config-schema';
|
||||
import type { ElasticsearchClient } from '@kbn/core/server';
|
||||
import { IRouter } from '@kbn/core/server';
|
||||
import { PROCESS_EVENTS_INDEX } from '@kbn/session-view-plugin/common/constants';
|
||||
import { COUNT_ROUTE } from '../../common/constants';
|
||||
|
||||
export const registerCountRoute = (router: IRouter) => {
|
||||
router.get(
|
||||
{
|
||||
path: COUNT_ROUTE,
|
||||
validate: {
|
||||
query: schema.object({
|
||||
query: schema.string(),
|
||||
field: schema.string(),
|
||||
index: schema.maybe(schema.string()),
|
||||
}),
|
||||
},
|
||||
},
|
||||
async (context, request, response) => {
|
||||
const client = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const { query, field, index } = request.query;
|
||||
|
||||
try {
|
||||
const body = await doCount(client, query, field, index);
|
||||
|
||||
return response.ok({ body });
|
||||
} catch (err) {
|
||||
return response.badRequest(err.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const doCount = async (
|
||||
client: ElasticsearchClient,
|
||||
query: string,
|
||||
field: string,
|
||||
index?: string
|
||||
) => {
|
||||
const queryDSL = JSON.parse(query);
|
||||
|
||||
const search = await client.search({
|
||||
index: [index || PROCESS_EVENTS_INDEX],
|
||||
body: {
|
||||
query: queryDSL,
|
||||
size: 0,
|
||||
aggs: {
|
||||
custom_count: {
|
||||
cardinality: {
|
||||
field,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const agg: any = search.aggregations?.custom_count;
|
||||
|
||||
return agg?.value || 0;
|
||||
};
|
|
@ -6,7 +6,10 @@
|
|||
*/
|
||||
import { IRouter } from '@kbn/core/server';
|
||||
import { RuleRegistryPluginStartContract } from '@kbn/rule-registry-plugin/server';
|
||||
import { registerAggregateRoute } from './aggregate';
|
||||
import { registerCountRoute } from './count';
|
||||
|
||||
export const registerRoutes = (router: IRouter, ruleRegistry: RuleRegistryPluginStartContract) => {
|
||||
// register new routes here
|
||||
registerAggregateRoute(router);
|
||||
registerCountRoute(router);
|
||||
};
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
{ "path": "../../../src/plugins/es_ui_shared/tsconfig.json" },
|
||||
{ "path": "../infra/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/kibana_utils/tsconfig.json" },
|
||||
{ "path": "../rule_registry/tsconfig.json" }
|
||||
{ "path": "../rule_registry/tsconfig.json" },
|
||||
{ "path": "../session_view/tsconfig.json" }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ export const PROCESS_EVENTS_ROUTE = '/internal/session_view/process_events_route
|
|||
export const ALERTS_ROUTE = '/internal/session_view/alerts_route';
|
||||
export const ALERT_STATUS_ROUTE = '/internal/session_view/alert_status_route';
|
||||
export const SESSION_ENTRY_LEADERS_ROUTE = '/internal/session_view/session_entry_leaders_route';
|
||||
export const PROCESS_EVENTS_INDEX = 'logs-endpoint.events.process-*';
|
||||
export const PROCESS_EVENTS_INDEX = 'logs-endpoint.events.process*';
|
||||
export const PREVIEW_ALERTS_INDEX = '.preview.alerts-security.alerts-default';
|
||||
export const ENTRY_SESSION_ENTITY_ID_PROPERTY = 'process.entry_leader.entity_id';
|
||||
export const ALERT_UUID_PROPERTY = 'kibana.alert.uuid';
|
||||
|
|
|
@ -40,16 +40,21 @@ export const registerAlertsRoute = (
|
|||
async (_context, request, response) => {
|
||||
const client = await ruleRegistry.getRacClientWithRequest(request);
|
||||
const { sessionEntityId, investigatedAlertId, range, cursor } = request.query;
|
||||
const body = await searchAlerts(
|
||||
client,
|
||||
sessionEntityId,
|
||||
ALERTS_PER_PAGE,
|
||||
investigatedAlertId,
|
||||
range,
|
||||
cursor
|
||||
);
|
||||
|
||||
return response.ok({ body });
|
||||
try {
|
||||
const body = await searchAlerts(
|
||||
client,
|
||||
sessionEntityId,
|
||||
ALERTS_PER_PAGE,
|
||||
investigatedAlertId,
|
||||
range,
|
||||
cursor
|
||||
);
|
||||
|
||||
return response.ok({ body });
|
||||
} catch (err) {
|
||||
return response.badRequest(err.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -70,60 +75,69 @@ export const searchAlerts = async (
|
|||
return { events: [] };
|
||||
}
|
||||
|
||||
const results = await client.find({
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
term: {
|
||||
[ENTRY_SESSION_ENTITY_ID_PROPERTY]: sessionEntityId,
|
||||
},
|
||||
},
|
||||
range && {
|
||||
range: {
|
||||
[ALERT_ORIGINAL_TIME_PROPERTY]: {
|
||||
gte: range[0],
|
||||
lte: range[1],
|
||||
try {
|
||||
const results = await client.find({
|
||||
query: {
|
||||
bool: {
|
||||
must: [
|
||||
{
|
||||
term: {
|
||||
[ENTRY_SESSION_ENTITY_ID_PROPERTY]: sessionEntityId,
|
||||
},
|
||||
},
|
||||
},
|
||||
].filter((item) => !!item),
|
||||
},
|
||||
},
|
||||
track_total_hits: true,
|
||||
size,
|
||||
index: indices.join(','),
|
||||
sort: [{ '@timestamp': 'asc' }],
|
||||
search_after: cursor ? [cursor] : undefined,
|
||||
});
|
||||
|
||||
// if an alert is being investigated, fetch it on it's own, as it's not guaranteed to come back in the above request.
|
||||
// we only need to do this for the first page of alerts.
|
||||
if (!cursor && investigatedAlertId) {
|
||||
const investigatedAlertSearch = await client.find({
|
||||
query: {
|
||||
match: {
|
||||
[ALERT_UUID_PROPERTY]: investigatedAlertId,
|
||||
range && {
|
||||
range: {
|
||||
[ALERT_ORIGINAL_TIME_PROPERTY]: {
|
||||
gte: range[0],
|
||||
lte: range[1],
|
||||
},
|
||||
},
|
||||
},
|
||||
].filter((item) => !!item),
|
||||
},
|
||||
},
|
||||
size: 1,
|
||||
track_total_hits: true,
|
||||
size,
|
||||
index: indices.join(','),
|
||||
sort: [{ '@timestamp': 'asc' }],
|
||||
search_after: cursor ? [cursor] : undefined,
|
||||
});
|
||||
|
||||
if (investigatedAlertSearch.hits.hits.length > 0) {
|
||||
results.hits.hits.unshift(investigatedAlertSearch.hits.hits[0]);
|
||||
// if an alert is being investigated, fetch it on it's own, as it's not guaranteed to come back in the above request.
|
||||
// we only need to do this for the first page of alerts.
|
||||
if (!cursor && investigatedAlertId) {
|
||||
const investigatedAlertSearch = await client.find({
|
||||
query: {
|
||||
match: {
|
||||
[ALERT_UUID_PROPERTY]: investigatedAlertId,
|
||||
},
|
||||
},
|
||||
size: 1,
|
||||
index: indices.join(','),
|
||||
});
|
||||
|
||||
if (investigatedAlertSearch.hits.hits.length > 0) {
|
||||
results.hits.hits.unshift(investigatedAlertSearch.hits.hits[0]);
|
||||
}
|
||||
}
|
||||
|
||||
const events = results.hits.hits.map((hit: any) => {
|
||||
// the alert indexes flattens many properties. this util unflattens them as session view expects structured json.
|
||||
hit._source = expandDottedObject(hit._source);
|
||||
|
||||
return hit;
|
||||
});
|
||||
|
||||
const total =
|
||||
typeof results.hits.total === 'number' ? results.hits.total : results.hits.total?.value;
|
||||
|
||||
return { total, events };
|
||||
} catch (err) {
|
||||
// unauthorized
|
||||
if (err.output.statusCode === 404) {
|
||||
return { total: 0, events: [] };
|
||||
}
|
||||
|
||||
throw err;
|
||||
}
|
||||
|
||||
const events = results.hits.hits.map((hit: any) => {
|
||||
// the alert indexes flattens many properties. this util unflattens them as session view expects structured json.
|
||||
hit._source = expandDottedObject(hit._source);
|
||||
|
||||
return hit;
|
||||
});
|
||||
|
||||
const total =
|
||||
typeof results.hits.total === 'number' ? results.hits.total : results.hits.total?.value;
|
||||
|
||||
return { total, events };
|
||||
};
|
||||
|
|
|
@ -40,16 +40,26 @@ export const registerProcessEventsRoute = (
|
|||
async (context, request, response) => {
|
||||
const client = (await context.core).elasticsearch.client.asCurrentUser;
|
||||
const alertsClient = await ruleRegistry.getRacClientWithRequest(request);
|
||||
const { sessionEntityId, cursor, forward = true } = request.query;
|
||||
const body = await fetchEventsAndScopedAlerts(
|
||||
client,
|
||||
alertsClient,
|
||||
sessionEntityId,
|
||||
cursor,
|
||||
forward
|
||||
);
|
||||
const { sessionEntityId, cursor, forward } = request.query;
|
||||
|
||||
return response.ok({ body });
|
||||
try {
|
||||
const body = await fetchEventsAndScopedAlerts(
|
||||
client,
|
||||
alertsClient,
|
||||
sessionEntityId,
|
||||
cursor,
|
||||
forward
|
||||
);
|
||||
|
||||
return response.ok({ body });
|
||||
} catch (err) {
|
||||
// unauthorized
|
||||
if (err.meta.statusCode === 403) {
|
||||
return response.ok({ body: { total: 0, events: [] } });
|
||||
}
|
||||
|
||||
return response.badRequest(err.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -58,7 +68,7 @@ export const fetchEventsAndScopedAlerts = async (
|
|||
client: ElasticsearchClient,
|
||||
alertsClient: AlertsClient,
|
||||
sessionEntityId: string,
|
||||
cursor: string | undefined,
|
||||
cursor?: string,
|
||||
forward = true
|
||||
) => {
|
||||
const cursorMillis = cursor && new Date(cursor).getTime() + (forward ? -1 : 1);
|
||||
|
|
|
@ -0,0 +1,200 @@
|
|||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "1",
|
||||
"source": {
|
||||
"event.kind" : "event",
|
||||
"@timestamp": "2020-12-16T15:16:18.570Z",
|
||||
"message": "hello world 1",
|
||||
"orchestrator.namespace": "namespace",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "2",
|
||||
"source": {
|
||||
"event.kind" : "event",
|
||||
"@timestamp": "2020-12-16T15:16:18.570Z",
|
||||
"message": "hello world 1",
|
||||
"orchestrator.namespace": "namespace",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "3",
|
||||
"source": {
|
||||
"event.kind" : "event",
|
||||
"@timestamp": "2020-12-16T15:16:19.570Z",
|
||||
"message": "hello world 1",
|
||||
"orchestrator.namespace": "namespace02",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "4",
|
||||
"source": {
|
||||
"event.kind" : "event",
|
||||
"@timestamp": "2020-12-16T15:16:20.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace02",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "5",
|
||||
"source": {
|
||||
"event.kind" : "event",
|
||||
"@timestamp": "2020-12-16T15:16:21.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace03",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "6",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:22.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace03",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "7",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:23.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace04",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "8",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:24.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace05",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "9",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:25.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace06",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "10",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:26.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace07",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "11",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:27.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace08",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "12",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:28.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace09",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "13",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:29.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace10",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
"type": "doc",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"id": "14",
|
||||
"source": {
|
||||
"@timestamp": "2020-12-16T15:16:30.570Z",
|
||||
"message": "hello world security",
|
||||
"orchestrator.namespace": "namespace11",
|
||||
"container.image.name": "debian11"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"index": "kubernetes-test-index",
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"orchestrator.namespace": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
},
|
||||
"container.image.name": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
5251
x-pack/test/functional/es_archives/session_view/alerts/mappings.json
Normal file
5251
x-pack/test/functional/es_archives/session_view/alerts/mappings.json
Normal file
File diff suppressed because it is too large
Load diff
206945
x-pack/test/functional/es_archives/session_view/process_events/data.json
Normal file
206945
x-pack/test/functional/es_archives/session_view/process_events/data.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"index": "logs-endpoint.events.process",
|
||||
"mappings": {
|
||||
"properties": {
|
||||
"message": {
|
||||
"type": "text",
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
},
|
||||
"process.entry_leader.entity_id": {
|
||||
"type": "keyword",
|
||||
"ignore_above": 256
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
x-pack/test/kubernetes_security/basic/config.ts
Normal file
15
x-pack/test/kubernetes_security/basic/config.ts
Normal 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 { createTestConfig } from '../common/config';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default createTestConfig({
|
||||
license: 'basic',
|
||||
name: 'X-Pack kubernetes_security API integration tests (basic)',
|
||||
testFiles: [require.resolve('./tests')],
|
||||
});
|
99
x-pack/test/kubernetes_security/basic/tests/aggregate.ts
Normal file
99
x-pack/test/kubernetes_security/basic/tests/aggregate.ts
Normal file
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { AGGREGATE_ROUTE } from '@kbn/kubernetes-security-plugin/common/constants';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
const MOCK_INDEX = 'kubernetes-test-index';
|
||||
const ORCHESTRATOR_NAMESPACE_PROPERTY = 'orchestrator.namespace';
|
||||
const CONTAINER_IMAGE_NAME_PROPERTY = 'container.image.name';
|
||||
const TIMESTAMP_PROPERTY = '@timestamp';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function aggregateTests({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
const namespaces = ['namespace', 'namespace02', 'namespace03', 'namespace04'];
|
||||
|
||||
describe('Kubernetes security with a basic license', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load(
|
||||
'x-pack/test/functional/es_archives/kubernetes_security/process_events'
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload(
|
||||
'x-pack/test/functional/es_archives/kubernetes_security/process_events'
|
||||
);
|
||||
});
|
||||
|
||||
it(`${AGGREGATE_ROUTE} returns aggregates on process events`, async () => {
|
||||
const response = await supertest
|
||||
.get(AGGREGATE_ROUTE)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.query({
|
||||
query: JSON.stringify({ match: { [CONTAINER_IMAGE_NAME_PROPERTY]: 'debian11' } }),
|
||||
groupBy: ORCHESTRATOR_NAMESPACE_PROPERTY,
|
||||
page: 0,
|
||||
index: MOCK_INDEX,
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
expect(response.body.length).to.be(10);
|
||||
|
||||
namespaces.forEach((namespace, i) => {
|
||||
expect(response.body[i].key).to.be(namespace);
|
||||
});
|
||||
});
|
||||
|
||||
it(`${AGGREGATE_ROUTE} allows pagination`, async () => {
|
||||
const response = await supertest
|
||||
.get(AGGREGATE_ROUTE)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.query({
|
||||
query: JSON.stringify({ match: { [CONTAINER_IMAGE_NAME_PROPERTY]: 'debian11' } }),
|
||||
groupBy: ORCHESTRATOR_NAMESPACE_PROPERTY,
|
||||
page: 1,
|
||||
index: MOCK_INDEX,
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
expect(response.body.length).to.be(1);
|
||||
expect(response.body[0].key).to.be('namespace11');
|
||||
});
|
||||
|
||||
it(`${AGGREGATE_ROUTE} allows a range query`, async () => {
|
||||
const response = await supertest
|
||||
.get(AGGREGATE_ROUTE)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.query({
|
||||
query: JSON.stringify({
|
||||
range: {
|
||||
[TIMESTAMP_PROPERTY]: {
|
||||
gte: '2020-12-16T15:16:28.570Z',
|
||||
lte: '2020-12-16T15:16:30.570Z',
|
||||
},
|
||||
},
|
||||
}),
|
||||
groupBy: ORCHESTRATOR_NAMESPACE_PROPERTY,
|
||||
page: 0,
|
||||
index: MOCK_INDEX,
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
expect(response.body.length).to.be(3);
|
||||
});
|
||||
|
||||
it(`${AGGREGATE_ROUTE} handles a bad request`, async () => {
|
||||
const response = await supertest.get(AGGREGATE_ROUTE).set('kbn-xsrf', 'foo').query({
|
||||
query: 'asdf',
|
||||
groupBy: ORCHESTRATOR_NAMESPACE_PROPERTY,
|
||||
page: 0,
|
||||
index: MOCK_INDEX,
|
||||
});
|
||||
expect(response.status).to.be(400);
|
||||
});
|
||||
});
|
||||
}
|
82
x-pack/test/kubernetes_security/basic/tests/count.ts
Normal file
82
x-pack/test/kubernetes_security/basic/tests/count.ts
Normal file
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import { COUNT_ROUTE } from '@kbn/kubernetes-security-plugin/common/constants';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
|
||||
const MOCK_INDEX = 'kubernetes-test-index';
|
||||
const ORCHESTRATOR_NAMESPACE_PROPERTY = 'orchestrator.namespace';
|
||||
const CONTAINER_IMAGE_NAME_PROPERTY = 'container.image.name';
|
||||
const TIMESTAMP_PROPERTY = '@timestamp';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function countTests({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('Kubernetes security with a basic license', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load(
|
||||
'x-pack/test/functional/es_archives/kubernetes_security/process_events'
|
||||
);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload(
|
||||
'x-pack/test/functional/es_archives/kubernetes_security/process_events'
|
||||
);
|
||||
});
|
||||
|
||||
it(`${COUNT_ROUTE} returns cardinality of a field`, async () => {
|
||||
const response = await supertest
|
||||
.get(COUNT_ROUTE)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.query({
|
||||
query: JSON.stringify({ match: { [CONTAINER_IMAGE_NAME_PROPERTY]: 'debian11' } }),
|
||||
field: ORCHESTRATOR_NAMESPACE_PROPERTY,
|
||||
index: MOCK_INDEX,
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
expect(response.body).to.be(11);
|
||||
});
|
||||
|
||||
it(`${COUNT_ROUTE} allows a range query`, async () => {
|
||||
const response = await supertest
|
||||
.get(COUNT_ROUTE)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.query({
|
||||
query: JSON.stringify({
|
||||
range: {
|
||||
[TIMESTAMP_PROPERTY]: {
|
||||
gte: '2020-12-16T15:16:28.570Z',
|
||||
lte: '2020-12-16T15:16:30.570Z',
|
||||
},
|
||||
},
|
||||
}),
|
||||
field: ORCHESTRATOR_NAMESPACE_PROPERTY,
|
||||
index: MOCK_INDEX,
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
expect(response.body).to.be(3);
|
||||
});
|
||||
|
||||
it(`${COUNT_ROUTE} handles a bad query`, async () => {
|
||||
const response = await supertest
|
||||
.get(COUNT_ROUTE)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.query({
|
||||
query: JSON.stringify({
|
||||
range: 'asdf',
|
||||
}),
|
||||
field: ORCHESTRATOR_NAMESPACE_PROPERTY,
|
||||
index: MOCK_INDEX,
|
||||
});
|
||||
expect(response.status).to.be(400);
|
||||
});
|
||||
});
|
||||
}
|
18
x-pack/test/kubernetes_security/basic/tests/index.ts
Normal file
18
x-pack/test/kubernetes_security/basic/tests/index.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* 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 '../../common/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function kubernetesSecurityApiIntegrationTests({
|
||||
loadTestFile,
|
||||
}: FtrProviderContext) {
|
||||
describe('Kubernetes security API (basic)', function () {
|
||||
loadTestFile(require.resolve('./aggregate'));
|
||||
loadTestFile(require.resolve('./count'));
|
||||
});
|
||||
}
|
39
x-pack/test/kubernetes_security/common/config.ts
Normal file
39
x-pack/test/kubernetes_security/common/config.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { FtrConfigProviderContext } from '@kbn/test';
|
||||
|
||||
interface Settings {
|
||||
license: 'basic' | 'trial';
|
||||
testFiles: string[];
|
||||
name: string;
|
||||
}
|
||||
|
||||
export function createTestConfig(settings: Settings) {
|
||||
const { testFiles, license, name } = settings;
|
||||
|
||||
return async ({ readConfigFile }: FtrConfigProviderContext) => {
|
||||
const xPackAPITestsConfig = await readConfigFile(
|
||||
require.resolve('../../api_integration/config.ts')
|
||||
);
|
||||
|
||||
return {
|
||||
testFiles,
|
||||
servers: xPackAPITestsConfig.get('servers'),
|
||||
services: xPackAPITestsConfig.get('services'),
|
||||
junit: {
|
||||
reportName: name,
|
||||
},
|
||||
|
||||
esTestCluster: {
|
||||
...xPackAPITestsConfig.get('esTestCluster'),
|
||||
license,
|
||||
},
|
||||
kbnTestServer: xPackAPITestsConfig.get('kbnTestServer'),
|
||||
};
|
||||
};
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type { FtrProviderContext } from '../../api_integration/ftr_provider_context';
|
15
x-pack/test/session_view/basic/config.ts
Normal file
15
x-pack/test/session_view/basic/config.ts
Normal 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 { createTestConfig } from '../common/config';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default createTestConfig({
|
||||
license: 'basic',
|
||||
name: 'X-Pack session_view API integration tests (basic)',
|
||||
testFiles: [require.resolve('./tests')],
|
||||
});
|
114
x-pack/test/session_view/basic/tests/index.ts
Normal file
114
x-pack/test/session_view/basic/tests/index.ts
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* 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 '../../common/ftr_provider_context';
|
||||
import {
|
||||
createUsersAndRoles,
|
||||
deleteUsersAndRoles,
|
||||
} from '../../../rule_registry/common/lib/authentication';
|
||||
|
||||
import {
|
||||
superUser,
|
||||
globalRead,
|
||||
secOnlyReadSpacesAll,
|
||||
obsOnlySpacesAll,
|
||||
noKibanaPrivileges,
|
||||
} from '../../../rule_registry/common/lib/authentication/users';
|
||||
|
||||
import { noKibanaPrivileges as noKibanaPrivilegesRole } from '../../../rule_registry/common/lib/authentication/roles';
|
||||
|
||||
import { Role } from '../../../rule_registry/common/lib/authentication/types';
|
||||
|
||||
const globalReadRole: Role = {
|
||||
name: 'global_read',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
privileges: ['all'],
|
||||
names: ['logs-*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
base: ['read'],
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const securitySolutionOnlyReadSpacesAll: Role = {
|
||||
name: 'sec_only_read_spaces_all',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
privileges: ['all'],
|
||||
names: ['logs-*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
siem: ['read'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export const observabilityOnlyAllSpacesAll: Role = {
|
||||
name: 'obs_only_all_spaces_all',
|
||||
privileges: {
|
||||
elasticsearch: {
|
||||
indices: [
|
||||
{
|
||||
privileges: ['all'],
|
||||
names: ['logs-*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
kibana: [
|
||||
{
|
||||
feature: {
|
||||
apm: ['all'],
|
||||
},
|
||||
spaces: ['*'],
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const users = [superUser, globalRead, secOnlyReadSpacesAll, obsOnlySpacesAll, noKibanaPrivileges];
|
||||
const roles = [
|
||||
globalReadRole,
|
||||
securitySolutionOnlyReadSpacesAll,
|
||||
observabilityOnlyAllSpacesAll,
|
||||
noKibanaPrivilegesRole,
|
||||
];
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function kubernetesSecurityApiIntegrationTests({
|
||||
loadTestFile,
|
||||
getService,
|
||||
}: FtrProviderContext) {
|
||||
describe('Session View API (basic)', function () {
|
||||
before(async () => {
|
||||
await createUsersAndRoles(getService, users, roles);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await deleteUsersAndRoles(getService, users, roles);
|
||||
});
|
||||
|
||||
loadTestFile(require.resolve('./process_events_route'));
|
||||
});
|
||||
}
|
160
x-pack/test/session_view/basic/tests/process_events_route.ts
Normal file
160
x-pack/test/session_view/basic/tests/process_events_route.ts
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* 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 expect from '@kbn/expect';
|
||||
import {
|
||||
PROCESS_EVENTS_ROUTE,
|
||||
PROCESS_EVENTS_PER_PAGE,
|
||||
} from '@kbn/session-view-plugin/common/constants';
|
||||
import { FtrProviderContext } from '../../common/ftr_provider_context';
|
||||
import { User } from '../../../rule_registry/common/lib/authentication/types';
|
||||
|
||||
import {
|
||||
superUser,
|
||||
globalRead,
|
||||
secOnlyReadSpacesAll,
|
||||
obsOnlySpacesAll,
|
||||
noKibanaPrivileges,
|
||||
} from '../../../rule_registry/common/lib/authentication/users';
|
||||
|
||||
const MOCK_SESSION_ENTITY_ID =
|
||||
'MDEwMTAxMDEtMDEwMS0wMTAxLTAxMDEtMDEwMTAxMDEwMTAxLTUyMDU3LTEzMjk2NDkxMDQwLjEzMDAwMDAwMA==';
|
||||
|
||||
interface TestCase {
|
||||
/** The ID of the alert */
|
||||
authorizedUsers: User[];
|
||||
/** Unauthorized users */
|
||||
unauthorizedUsers: User[];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function processEventsTests({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe(`Session view - ${PROCESS_EVENTS_ROUTE} - with a basic license`, () => {
|
||||
before(async () => {
|
||||
await esArchiver.load('x-pack/test/functional/es_archives/session_view/process_events');
|
||||
await esArchiver.load('x-pack/test/functional/es_archives/session_view/alerts');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload('x-pack/test/functional/es_archives/session_view/process_events');
|
||||
await esArchiver.unload('x-pack/test/functional/es_archives/session_view/alerts');
|
||||
});
|
||||
|
||||
it(`${PROCESS_EVENTS_ROUTE} returns a page of process events`, async () => {
|
||||
const response = await supertest.get(PROCESS_EVENTS_ROUTE).set('kbn-xsrf', 'foo').query({
|
||||
sessionEntityId: MOCK_SESSION_ENTITY_ID,
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
expect(response.body.total).to.be(504);
|
||||
expect(response.body.events.length).to.be(PROCESS_EVENTS_PER_PAGE);
|
||||
});
|
||||
|
||||
it(`${PROCESS_EVENTS_ROUTE} returns a page of process events (w alerts) (paging forward)`, async () => {
|
||||
const response = await supertest.get(PROCESS_EVENTS_ROUTE).set('kbn-xsrf', 'foo').query({
|
||||
sessionEntityId: MOCK_SESSION_ENTITY_ID,
|
||||
cursor: '2022-05-10T20:39:23.6817084Z', // paginating from the timestamp of the first alert.
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
|
||||
const alerts = response.body.events.filter(
|
||||
(event: any) => event._source.event.kind === 'signal'
|
||||
);
|
||||
|
||||
expect(alerts.length).to.above(0);
|
||||
});
|
||||
|
||||
it(`${PROCESS_EVENTS_ROUTE} returns a page of process events (w alerts) (paging backwards)`, async () => {
|
||||
const response = await supertest.get(PROCESS_EVENTS_ROUTE).set('kbn-xsrf', 'foo').query({
|
||||
sessionEntityId: MOCK_SESSION_ENTITY_ID,
|
||||
cursor: '2022-05-10T20:39:23.6817084Z',
|
||||
forward: false,
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
|
||||
const alerts = response.body.events.filter(
|
||||
(event: any) => event._source.event.kind === 'signal'
|
||||
);
|
||||
|
||||
expect(alerts.length).to.be(1); // only one since we are starting at the cursor of the first alert in the esarchiver data, and working backwards.
|
||||
|
||||
const events = response.body.events.filter(
|
||||
(event: any) => event._source.event.kind === 'event'
|
||||
);
|
||||
|
||||
expect(events[0]._source['@timestamp']).to.be.below(
|
||||
events[events.length - 1]._source['@timestamp']
|
||||
);
|
||||
});
|
||||
|
||||
function addTests({ authorizedUsers, unauthorizedUsers }: TestCase) {
|
||||
authorizedUsers.forEach(({ username, password }) => {
|
||||
it(`${username} should be able to view alerts in session view`, async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.get(`${PROCESS_EVENTS_ROUTE}`)
|
||||
.auth(username, password)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.query({
|
||||
sessionEntityId: MOCK_SESSION_ENTITY_ID,
|
||||
cursor: '2022-05-10T20:39:23.6817084Z', // paginating from the timestamp of the first alert.
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
|
||||
const alerts = response.body.events.filter(
|
||||
(event: any) => event._source.event.kind === 'signal'
|
||||
);
|
||||
|
||||
expect(alerts.length).to.above(0);
|
||||
});
|
||||
});
|
||||
|
||||
unauthorizedUsers.forEach(({ username, password }) => {
|
||||
it(`${username} should NOT be able to view alerts in session view`, async () => {
|
||||
const response = await supertestWithoutAuth
|
||||
.get(`${PROCESS_EVENTS_ROUTE}`)
|
||||
.auth(username, password)
|
||||
.set('kbn-xsrf', 'true')
|
||||
.query({
|
||||
sessionEntityId: MOCK_SESSION_ENTITY_ID,
|
||||
cursor: '2022-05-10T20:39:23.6817084Z', // paginating from the timestamp of the first alert.
|
||||
});
|
||||
expect(response.status).to.be(200);
|
||||
|
||||
if (username === 'no_kibana_privileges') {
|
||||
expect(response.body.events.length).to.be.equal(0);
|
||||
} else {
|
||||
// process events should still load (since logs-* is granted, except for no_kibana_privileges user)
|
||||
expect(response.body.events.length).to.be.above(0);
|
||||
}
|
||||
|
||||
const alerts = response.body.events.filter(
|
||||
(event: any) => event._source.event.kind === 'signal'
|
||||
);
|
||||
|
||||
expect(alerts.length).to.be(0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('Session View', () => {
|
||||
const authorizedInAllSpaces = [superUser, globalRead, secOnlyReadSpacesAll];
|
||||
const unauthorized = [
|
||||
// these users are not authorized to get alerts for session view
|
||||
obsOnlySpacesAll,
|
||||
noKibanaPrivileges,
|
||||
];
|
||||
|
||||
addTests({
|
||||
authorizedUsers: [...authorizedInAllSpaces],
|
||||
unauthorizedUsers: [...unauthorized],
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
39
x-pack/test/session_view/common/config.ts
Normal file
39
x-pack/test/session_view/common/config.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { FtrConfigProviderContext } from '@kbn/test';
|
||||
|
||||
interface Settings {
|
||||
license: 'basic' | 'trial';
|
||||
testFiles: string[];
|
||||
name: string;
|
||||
}
|
||||
|
||||
export function createTestConfig(settings: Settings) {
|
||||
const { testFiles, license, name } = settings;
|
||||
|
||||
return async ({ readConfigFile }: FtrConfigProviderContext) => {
|
||||
const xPackAPITestsConfig = await readConfigFile(
|
||||
require.resolve('../../api_integration/config.ts')
|
||||
);
|
||||
|
||||
return {
|
||||
testFiles,
|
||||
servers: xPackAPITestsConfig.get('servers'),
|
||||
services: xPackAPITestsConfig.get('services'),
|
||||
junit: {
|
||||
reportName: name,
|
||||
},
|
||||
|
||||
esTestCluster: {
|
||||
...xPackAPITestsConfig.get('esTestCluster'),
|
||||
license,
|
||||
},
|
||||
kbnTestServer: xPackAPITestsConfig.get('kbnTestServer'),
|
||||
};
|
||||
};
|
||||
}
|
8
x-pack/test/session_view/common/ftr_provider_context.ts
Normal file
8
x-pack/test/session_view/common/ftr_provider_context.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export type { FtrProviderContext } from '../../api_integration/ftr_provider_context';
|
Loading…
Add table
Add a link
Reference in a new issue