[Serverless][Observability] Use roles-based testing - api_integration (#184654)

part of: [#184033](https://github.com/elastic/kibana/issues/184033)

## Summary

This PR changes the observability serverless tests (and impacted
security tests) to not run with operator privileges.


### How to test

- Follow the steps from
https://github.com/elastic/kibana/blob/main/x-pack/test_serverless/README.md#run-tests-on-mki
This commit is contained in:
Carlos Crespo 2024-06-07 17:34:28 +02:00 committed by GitHub
parent 93c45874a3
commit 860f8dbf13
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
36 changed files with 862 additions and 589 deletions

View file

@ -20,21 +20,38 @@ export interface UsageStatsPayloadTestFriendly extends UsageStatsPayload {
export function UsageAPIProvider({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
async function getTelemetryStats(payload: {
unencrypted: true;
refreshCache?: boolean;
}): Promise<Array<{ clusterUuid: string; stats: UsageStatsPayloadTestFriendly }>>;
async function getTelemetryStats(payload: {
unencrypted: false;
refreshCache?: boolean;
}): Promise<Array<{ clusterUuid: string; stats: string }>>;
async function getTelemetryStats(payload: {
unencrypted?: boolean;
refreshCache?: boolean;
}): Promise<Array<{ clusterUuid: string; stats: UsageStatsPayloadTestFriendly | string }>> {
async function getTelemetryStats(
payload: {
unencrypted: true;
refreshCache?: boolean;
},
options?: { authHeader: Record<string, string> }
): Promise<Array<{ clusterUuid: string; stats: UsageStatsPayloadTestFriendly }>>;
async function getTelemetryStats(
payload: {
unencrypted: false;
refreshCache?: boolean;
},
options?: { authHeader: Record<string, string> }
): Promise<Array<{ clusterUuid: string; stats: string }>>;
async function getTelemetryStats(
payload: {
unencrypted: false;
refreshCache?: boolean;
},
options?: { authHeader: Record<string, string> }
): Promise<Array<{ clusterUuid: string; stats: string }>>;
async function getTelemetryStats(
payload: {
unencrypted?: boolean;
refreshCache?: boolean;
},
options?: { authHeader: Record<string, string> }
): Promise<Array<{ clusterUuid: string; stats: UsageStatsPayloadTestFriendly | string }>> {
const { body } = await supertest
.post('/internal/telemetry/clusters/_stats')
.set('kbn-xsrf', 'xxx')
.set(options?.authHeader ?? {})
.set(ELASTIC_HTTP_VERSION_HEADER, '2')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send({ refreshCache: true, ...payload })

View file

@ -10,6 +10,7 @@ import {
FetchHistoricalSummaryResponse,
} from '@kbn/slo-schema';
import * as t from 'io-ts';
import type { RoleCredentials } from '../../shared/services';
import { FtrProviderContext } from '../ftr_provider_context';
type DurationUnit = 'm' | 'h' | 'd' | 'w' | 'M';
@ -70,50 +71,58 @@ type FetchHistoricalSummaryParams = t.OutputOf<
export function SloApiProvider({ getService }: FtrProviderContext) {
const es = getService('es');
const supertest = getService('supertest');
const svlCommonApi = getService('svlCommonApi');
const retry = getService('retry');
const requestTimeout = 30 * 1000;
const retryTimeout = 180 * 1000;
return {
async create(slo: SloParams) {
async create(slo: SloParams, roleAuthc: RoleCredentials) {
const { body } = await supertest
.post(`/api/observability/slos`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.send(slo);
return body;
},
async delete(sloId: string) {
async delete({ sloId, roleAuthc }: { sloId: string; roleAuthc: RoleCredentials }) {
const response = await supertest
.delete(`/api/observability/slos/${sloId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader);
return response;
},
async fetchHistoricalSummary(
params: FetchHistoricalSummaryParams
params: FetchHistoricalSummaryParams,
roleAuthc: RoleCredentials
): Promise<FetchHistoricalSummaryResponse> {
const { body } = await supertest
.post(`/internal/observability/slos/_historical_summary`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.send(params);
return body;
},
async waitForSloToBeDeleted(sloId: string) {
async waitForSloToBeDeleted({
sloId,
roleAuthc,
}: {
sloId: string;
roleAuthc: RoleCredentials;
}) {
if (!sloId) {
throw new Error(`sloId is undefined`);
}
return await retry.tryForTime(retryTimeout, async () => {
const response = await supertest
.delete(`/api/observability/slos/${sloId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.timeout(requestTimeout);
if (!response.ok) {
throw new Error(`slodId [${sloId}] was not deleted`);
@ -122,15 +131,15 @@ export function SloApiProvider({ getService }: FtrProviderContext) {
});
},
async waitForSloCreated({ sloId }: { sloId: string }) {
async waitForSloCreated({ sloId, roleAuthc }: { sloId: string; roleAuthc: RoleCredentials }) {
if (!sloId) {
throw new Error(`'sloId is undefined`);
}
return await retry.tryForTime(retryTimeout, async () => {
const response = await supertest
.get(`/api/observability/slos/${sloId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.timeout(requestTimeout);
if (response.body.id === undefined) {
throw new Error(`No slo with id ${sloId} found`);
@ -187,16 +196,14 @@ export function SloApiProvider({ getService }: FtrProviderContext) {
async deleteAllSLOs() {
const response = await supertest
.get(`/api/observability/slos/_definitions`)
.set('kbn-xsrf', 'true')
.set('x-elastic-internal-origin', 'foo')
.set(svlCommonApi.getInternalRequestHeader())
.send()
.expect(200);
await Promise.all(
response.body.results.map(({ id }: { id: string }) => {
return supertest
.delete(`/api/observability/slos/${id}`)
.set('kbn-xsrf', 'true')
.set('x-elastic-internal-origin', 'foo')
.set(svlCommonApi.getInternalRequestHeader())
.send()
.expect(204);
})

View file

@ -5,13 +5,13 @@
* 2.0.
*/
import type SuperTest from 'supertest';
import { CASES_URL } from '@kbn/cases-plugin/common';
import { Case, CaseSeverity, CaseStatuses } from '@kbn/cases-plugin/common/types/domain';
import type { CasePostRequest } from '@kbn/cases-plugin/common/types/api';
import { ConnectorTypes } from '@kbn/cases-plugin/common/types/domain';
import { CasesFindResponse } from '@kbn/cases-plugin/common/types/api';
import { kbnTestConfig, kibanaTestSuperuserServerless } from '@kbn/test';
import type { RoleCredentials } from '../../../shared/services';
import { FtrProviderContext } from '../../ftr_provider_context';
export interface User {
@ -23,13 +23,8 @@ export interface User {
export function SvlCasesApiServiceProvider({ getService }: FtrProviderContext) {
const kbnServer = getService('kibanaServer');
const supertest = getService('supertest');
const superUser: User = {
username: 'superuser',
password: 'superuser',
roles: ['superuser'],
};
const supertestWithoutAuth = getService('supertestWithoutAuth');
const svlCommonApi = getService('svlCommonApi');
const defaultUser = {
email: null,
@ -57,22 +52,6 @@ export function SvlCasesApiServiceProvider({ getService }: FtrProviderContext) {
};
return {
setupAuth({
apiCall,
headers,
auth,
}: {
apiCall: SuperTest.Test;
headers: Record<string, unknown>;
auth?: { user: User; space: string | null } | null;
}): SuperTest.Test {
if (!Object.hasOwn(headers, 'Cookie') && auth != null) {
return apiCall.auth(auth.user.username, auth.user.password);
}
return apiCall;
},
getSpaceUrlPrefix(spaceId: string | undefined | null) {
return spaceId && spaceId !== 'default' ? `/s/${spaceId}` : ``;
},
@ -139,65 +118,65 @@ export function SvlCasesApiServiceProvider({ getService }: FtrProviderContext) {
async createCase(
params: CasePostRequest,
expectedHttpCode: number = 200,
auth: { user: User; space: string | null } | null = { user: superUser, space: null },
headers: Record<string, string | string[]> = {}
roleAuthc: RoleCredentials,
expectedHttpCode: number = 200
): Promise<Case> {
const apiCall = supertest.post(`${CASES_URL}`);
this.setupAuth({ apiCall, headers, auth });
const apiCall = supertestWithoutAuth.post(`${CASES_URL}`);
const response = await apiCall
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.set(headers)
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.send(params)
.expect(expectedHttpCode);
return response.body;
},
async findCases({
query = {},
expectedHttpCode = 200,
auth = { user: superUser, space: null },
}: {
query?: Record<string, unknown>;
expectedHttpCode?: number;
auth?: { user: User; space: string | null };
}): Promise<CasesFindResponse> {
const { body: res } = await supertest
.get(`${this.getSpaceUrlPrefix(auth.space)}${CASES_URL}/_find`)
.auth(auth.user.username, auth.user.password)
async findCases(
{
query = {},
expectedHttpCode = 200,
space = 'default',
}: {
query?: Record<string, unknown>;
expectedHttpCode?: number;
space?: string;
},
roleAuthc: RoleCredentials
): Promise<CasesFindResponse> {
const { body: res } = await supertestWithoutAuth
.get(`${this.getSpaceUrlPrefix(space)}${CASES_URL}/_find`)
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.query({ sortOrder: 'asc', ...query })
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.send()
.expect(expectedHttpCode);
return res;
},
async getCase({
caseId,
includeComments = false,
expectedHttpCode = 200,
auth = { user: superUser, space: null },
}: {
caseId: string;
includeComments?: boolean;
expectedHttpCode?: number;
auth?: { user: User; space: string | null };
}): Promise<Case> {
const { body: theCase } = await supertest
async getCase(
{
caseId,
space = 'default',
includeComments = false,
expectedHttpCode = 200,
}: {
caseId: string;
space?: string;
includeComments?: boolean;
expectedHttpCode?: number;
},
roleAuthc: RoleCredentials
): Promise<Case> {
const { body: theCase } = await supertestWithoutAuth
.get(
`${this.getSpaceUrlPrefix(
auth?.space
space
)}${CASES_URL}/${caseId}?includeComments=${includeComments}`
)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.auth(auth.user.username, auth.user.password)
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.expect(expectedHttpCode);
return theCase;

View file

@ -54,7 +54,6 @@ export default function ({ getService }: FtrProviderContext) {
let roleAdmin: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
const supertest = getService('supertest');
const esClient = getService('es');
const objectRemover = new ObjectRemover(supertest);

View file

@ -31,7 +31,7 @@ import {
waitForExecutionEventLog,
waitForNumRuleRuns,
} from './helpers/alerting_wait_for_helpers';
import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
@ -60,14 +60,8 @@ export default function ({ getService }: FtrProviderContext) {
});
afterEach(async () => {
await supertest
.delete(`/api/actions/connector/${connectorId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/actions/connector/${connectorId}`).set(internalReqHeader);
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: '.kibana-event-log-*',
conflicts: 'proceed',

View file

@ -14,6 +14,7 @@ import type {
import { Config, kbnTestConfig, kibanaTestSuperuserServerless } from '@kbn/test';
import type { APIEndpoint } from '@kbn/apm-plugin/server';
import { formatRequest } from '@kbn/server-route-repository';
import type { InternalRequestHeader, RoleCredentials } from '../../../../../shared/services';
import { InheritedFtrProviderContext } from '../../../../services';
export function createApmApiClient(st: supertest.Agent) {
@ -21,20 +22,18 @@ export function createApmApiClient(st: supertest.Agent) {
options: {
type?: 'form-data';
endpoint: TEndpoint;
roleAuthc: RoleCredentials;
internalReqHeader: InternalRequestHeader;
} & APIClientRequestParamsOf<TEndpoint> & { params?: { query?: { _inspect?: boolean } } }
): Promise<SupertestReturnType<TEndpoint>> => {
const { endpoint, type } = options;
const { endpoint, type, roleAuthc, internalReqHeader } = options;
const params = 'params' in options ? (options.params as Record<string, any>) : {};
const { method, pathname, version } = formatRequest(endpoint, params.path);
const url = format({ pathname, query: params?.query });
const headers: Record<string, string> = {
'kbn-xsrf': 'foo',
'x-elastic-internal-origin': 'foo',
};
const headers: Record<string, string> = { ...internalReqHeader, ...roleAuthc.apiKeyHeader };
if (version) {
headers['Elastic-Api-Version'] = version;
}

View file

@ -6,6 +6,7 @@
*/
import expect from 'expect';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
import { APMFtrContextProvider } from './common/services';
import { ApmApiClient } from './common/apm_api_supertest';
@ -49,7 +50,11 @@ const SAMPLE_SOURCEMAP = {
mappings: 'A,AAAB;;ABCDE;',
};
async function uploadSourcemap(apmApiClient: ApmApiClient) {
async function uploadSourcemap(
apmApiClient: ApmApiClient,
roleAuthc: RoleCredentials,
internalReqHeader: InternalRequestHeader
) {
const response = await apmApiClient.slsUser({
endpoint: 'POST /api/apm/sourcemaps 2023-10-31',
type: 'form-data',
@ -61,14 +66,30 @@ async function uploadSourcemap(apmApiClient: ApmApiClient) {
sourcemap: JSON.stringify(SAMPLE_SOURCEMAP),
},
},
roleAuthc,
internalReqHeader,
});
return response.body;
}
export default function ({ getService }: APMFtrContextProvider) {
const apmApiClient = getService('apmApiClient');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
describe('apm feature flags', () => {
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
before(async () => {
internalReqHeader = svlCommonApi.getInternalRequestHeader();
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
describe('fleet migrations', () => {
it('rejects requests to save apm server schema', async () => {
try {
@ -81,6 +102,8 @@ export default function ({ getService }: APMFtrContextProvider) {
},
},
},
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(fleetMigrationResponse.statusCode);
@ -92,6 +115,8 @@ export default function ({ getService }: APMFtrContextProvider) {
try {
await apmApiClient.slsUser({
endpoint: 'GET /internal/apm/fleet/apm_server_schema/unsupported',
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(fleetMigrationResponse.statusCode);
@ -103,6 +128,8 @@ export default function ({ getService }: APMFtrContextProvider) {
try {
await apmApiClient.slsUser({
endpoint: 'GET /internal/apm/fleet/migration_check',
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(fleetMigrationResponse.statusCode);
@ -116,6 +143,8 @@ export default function ({ getService }: APMFtrContextProvider) {
try {
await apmApiClient.slsUser({
endpoint: 'GET /api/apm/settings/agent-configuration 2023-10-31',
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(agentConfigurationResponse.statusCode);
@ -127,6 +156,8 @@ export default function ({ getService }: APMFtrContextProvider) {
try {
await apmApiClient.slsUser({
endpoint: 'GET /api/apm/settings/agent-configuration/view 2023-10-31',
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(agentConfigurationResponse.statusCode);
@ -143,6 +174,8 @@ export default function ({ getService }: APMFtrContextProvider) {
service: {},
},
},
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(agentConfigurationResponse.statusCode);
@ -160,6 +193,8 @@ export default function ({ getService }: APMFtrContextProvider) {
settings: { transaction_sample_rate: '0.55' },
},
},
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(agentConfigurationResponse.statusCode);
@ -177,6 +212,8 @@ export default function ({ getService }: APMFtrContextProvider) {
etag: '7312bdcc34999629a3d39df24ed9b2a7553c0c39',
},
},
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(agentConfigurationResponse.statusCode);
@ -190,6 +227,8 @@ export default function ({ getService }: APMFtrContextProvider) {
try {
await apmApiClient.slsUser({
endpoint: 'GET /api/apm/sourcemaps 2023-10-31',
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(sourceMapsResponse.statusCode);
@ -199,7 +238,7 @@ export default function ({ getService }: APMFtrContextProvider) {
it('rejects requests to upload source maps', async () => {
try {
await uploadSourcemap(apmApiClient);
await uploadSourcemap(apmApiClient, roleAuthc, internalReqHeader);
} catch (err) {
expect(err.res.status).toBe(sourceMapsResponse.statusCode);
expect(err.res.body).toStrictEqual(sourceMapsResponse);
@ -211,6 +250,8 @@ export default function ({ getService }: APMFtrContextProvider) {
await apmApiClient.slsUser({
endpoint: 'DELETE /api/apm/sourcemaps/{id} 2023-10-31',
params: { path: { id: 'foo' } },
roleAuthc,
internalReqHeader,
});
} catch (err) {
expect(err.res.status).toBe(sourceMapsResponse.statusCode);

View file

@ -14,7 +14,7 @@
import { cleanup, Dataset, generate, PartialConfig } from '@kbn/data-forge';
import expect from '@kbn/expect';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { RoleCredentials } from '../../../../shared/services';
import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
export default function ({ getService }: FtrProviderContext) {
const esClient = getService('es');
@ -25,7 +25,9 @@ export default function ({ getService }: FtrProviderContext) {
const dataViewApi = getService('dataViewApi');
const sloApi = getService('sloApi');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
describe('Burn rate rule', () => {
const RULE_TYPE_ID = 'slo.rules.burnRate';
@ -41,6 +43,7 @@ export default function ({ getService }: FtrProviderContext) {
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
dataForgeConfig = {
schedule: [
{
@ -63,17 +66,12 @@ export default function ({ getService }: FtrProviderContext) {
id: DATA_VIEW_ID,
title: DATA_VIEW,
});
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/actions/connector/${actionId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: '.kibana-event-log-*',
query: { term: { 'rule.id': ruleId } },
@ -82,10 +80,7 @@ export default function ({ getService }: FtrProviderContext) {
await dataViewApi.delete({
id: DATA_VIEW_ID,
});
await supertest
.delete('/api/observability/slos/my-custom-id')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete('/api/observability/slos/my-custom-id').set(internalReqHeader);
await esDeleteAllIndices([ALERT_ACTION_INDEX, ...dataForgeIndices]);
await cleanup({ client: esClient, config: dataForgeConfig, logger });
@ -100,29 +95,32 @@ export default function ({ getService }: FtrProviderContext) {
indexName: ALERT_ACTION_INDEX,
});
await sloApi.create({
id: 'my-custom-id',
name: 'my custom name',
description: 'my custom description',
indicator: {
type: 'sli.kql.custom',
params: {
index: DATA_VIEW,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
await sloApi.create(
{
id: 'my-custom-id',
name: 'my custom name',
description: 'my custom description',
indicator: {
type: 'sli.kql.custom',
params: {
index: DATA_VIEW,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
},
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: '*',
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: '*',
});
roleAuthc
);
const dependencyRule = await alertingApi.createRule({
roleAuthc,

View file

@ -5,19 +5,28 @@
* 2.0.
*/
import { CasePostRequest } from '@kbn/cases-plugin/common/types/api';
import expect from '@kbn/expect';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default ({ getService }: FtrProviderContext): void => {
const svlCases = getService('svlCases');
const svlUserManager = getService('svlUserManager');
let findCasesResp: any;
let postCaseReq: any;
let postCaseReq: CasePostRequest;
describe('find_cases', () => {
let roleAuthc: RoleCredentials;
before(async () => {
findCasesResp = svlCases.api.getFindCasesResp();
postCaseReq = svlCases.api.getPostCaseReq('observability');
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
afterEach(async () => {
@ -25,16 +34,16 @@ export default ({ getService }: FtrProviderContext): void => {
});
it('should return empty response', async () => {
const cases = await svlCases.api.findCases({});
const cases = await svlCases.api.findCases({}, roleAuthc);
expect(cases).to.eql(findCasesResp);
});
it('should return cases', async () => {
const a = await svlCases.api.createCase(postCaseReq);
const b = await svlCases.api.createCase(postCaseReq);
const c = await svlCases.api.createCase(postCaseReq);
const a = await svlCases.api.createCase(postCaseReq, roleAuthc);
const b = await svlCases.api.createCase(postCaseReq, roleAuthc);
const c = await svlCases.api.createCase(postCaseReq, roleAuthc);
const cases = await svlCases.api.findCases({});
const cases = await svlCases.api.findCases({}, roleAuthc);
expect(cases).to.eql({
...findCasesResp,
@ -45,14 +54,22 @@ export default ({ getService }: FtrProviderContext): void => {
});
it('returns empty response when trying to find cases with owner as cases', async () => {
const cases = await svlCases.api.findCases({ query: { owner: 'cases' } });
const cases = await svlCases.api.findCases(
{
query: { owner: 'cases' },
},
roleAuthc
);
expect(cases).to.eql(findCasesResp);
});
it('returns empty response when trying to find cases with owner as securitySolution', async () => {
const cases = await svlCases.api.findCases({
query: { owner: 'securitySolution' },
});
const cases = await svlCases.api.findCases(
{
query: { owner: 'securitySolution' },
},
roleAuthc
);
expect(cases).to.eql(findCasesResp);
});
});

View file

@ -6,28 +6,47 @@
*/
import expect from '@kbn/expect';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default ({ getService }: FtrProviderContext): void => {
const svlCases = getService('svlCases');
const svlUserManager = getService('svlUserManager');
describe('get_case', () => {
let roleAuthc: RoleCredentials;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
afterEach(async () => {
await svlCases.api.deleteCases();
});
it('should return a case', async () => {
const postedCase = await svlCases.api.createCase(
svlCases.api.getPostCaseRequest('observability')
svlCases.api.getPostCaseRequest('observability'),
roleAuthc
);
const theCase = await svlCases.api.getCase(
{
caseId: postedCase.id,
includeComments: true,
},
roleAuthc
);
const theCase = await svlCases.api.getCase({
caseId: postedCase.id,
includeComments: true,
});
const data = svlCases.omit.removeServerGeneratedPropertiesFromCase(theCase);
expect(data).to.eql(svlCases.api.postCaseResp('observability'));
const { created_by: createdBy, ...data } =
svlCases.omit.removeServerGeneratedPropertiesFromCase(theCase);
const { created_by: _, ...expectedData } = svlCases.api.postCaseResp('observability');
expect(data).to.eql(expectedData);
expect(createdBy).to.have.keys('full_name', 'email', 'username');
expect(data.comments?.length).to.eql(0);
});
});

View file

@ -7,13 +7,24 @@
import expect from '@kbn/expect';
import { ConnectorTypes } from '@kbn/cases-plugin/common/types/domain';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default ({ getService }: FtrProviderContext): void => {
const svlCases = getService('svlCases');
const svlUserManager = getService('svlUserManager');
describe('post_case', () => {
let roleAuthc: RoleCredentials;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
afterEach(async () => {
await svlCases.api.deleteCases();
});
@ -29,6 +40,7 @@ export default ({ getService }: FtrProviderContext): void => {
fields: { issueType: 'Task', priority: 'High', parent: null },
},
}),
roleAuthc,
200
)
);
@ -40,6 +52,7 @@ export default ({ getService }: FtrProviderContext): void => {
svlCases.api.getPostCaseRequest('observability', {
owner: 'securitySolution',
}),
roleAuthc,
403
)
);
@ -51,6 +64,7 @@ export default ({ getService }: FtrProviderContext): void => {
svlCases.api.getPostCaseRequest('observability', {
owner: 'cases',
}),
roleAuthc,
403
)
);

View file

@ -13,10 +13,11 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils';
import { parseSearchParams } from '@kbn/share-plugin/common/url_service';
import { omit } from 'lodash';
import { COMPARATORS } from '@kbn/alerting-comparators';
import { kbnTestConfig } from '@kbn/test';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { ISO_DATE_REGEX } from './constants';
import { ActionDocument, LogsExplorerLocatorParsedParams } from './typings';
import { RoleCredentials } from '../../../../shared/services';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
export default function ({ getService }: FtrProviderContext) {
const esClient = getService('es');
@ -25,8 +26,10 @@ export default function ({ getService }: FtrProviderContext) {
const alertingApi = getService('alertingApi');
const dataViewApi = getService('dataViewApi');
const logger = getService('log');
const svlCommonApi = getService('svlCommonApi');
const svlUserManager = getService('svlUserManager');
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
describe('Custom Threshold rule - AVG - PCT - FIRED', () => {
const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default';
@ -42,6 +45,7 @@ export default function ({ getService }: FtrProviderContext) {
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
dataForgeConfig = {
schedule: [
{
@ -71,14 +75,8 @@ export default function ({ getService }: FtrProviderContext) {
});
after(async () => {
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/actions/connector/${actionId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: CUSTOM_THRESHOLD_RULE_ALERT_INDEX,
query: { term: { 'kibana.alert.rule.uuid': ruleId } },
@ -234,9 +232,10 @@ export default function ({ getService }: FtrProviderContext) {
docCountTarget: 1,
});
const { protocol, hostname, port } = kbnTestConfig.getUrlParts();
expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`http://localhost:5620/app/observability/alerts/${alertId}`
`${protocol}://${hostname}${port ? `:${port}` : ''}/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Average system.cpu.user.pct is 250%, above the threshold of 50%. (duration: 5 mins, data view: ${DATA_VIEW_NAME})`

View file

@ -12,10 +12,11 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils';
import { parseSearchParams } from '@kbn/share-plugin/common/url_service';
import { omit } from 'lodash';
import { COMPARATORS } from '@kbn/alerting-comparators';
import { kbnTestConfig } from '@kbn/test';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { ISO_DATE_REGEX } from './constants';
import { ActionDocument, LogsExplorerLocatorParsedParams } from './typings';
import { RoleCredentials } from '../../../../shared/services';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
export default function ({ getService }: FtrProviderContext) {
const esClient = getService('es');
@ -24,7 +25,9 @@ export default function ({ getService }: FtrProviderContext) {
const dataViewApi = getService('dataViewApi');
const esDeleteAllIndices = getService('esDeleteAllIndices');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
describe('Custom Threshold rule - AVG - PCT - NoData', () => {
const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default';
@ -38,6 +41,7 @@ export default function ({ getService }: FtrProviderContext) {
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
await dataViewApi.create({
name: DATA_VIEW_NAME,
id: DATA_VIEW_ID,
@ -46,14 +50,8 @@ export default function ({ getService }: FtrProviderContext) {
});
after(async () => {
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/actions/connector/${actionId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: CUSTOM_THRESHOLD_RULE_ALERT_INDEX,
query: { term: { 'kibana.alert.rule.uuid': ruleId } },
@ -210,9 +208,10 @@ export default function ({ getService }: FtrProviderContext) {
docCountTarget: 1,
});
const { protocol, hostname, port } = kbnTestConfig.getUrlParts();
expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`http://localhost:5620/app/observability/alerts/${alertId}`
`${protocol}://${hostname}${port ? `:${port}` : ''}/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
'Average system.cpu.user.pct reported no data in the last 5m'

View file

@ -17,7 +17,8 @@ import { COMPARATORS } from '@kbn/alerting-comparators';
import { FIRED_ACTIONS_ID } from '@kbn/observability-plugin/server/lib/rules/custom_threshold/constants';
import expect from '@kbn/expect';
import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils';
import { RoleCredentials } from '../../../../shared/services';
import { kbnTestConfig } from '@kbn/test';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { ActionDocument } from './typings';
@ -29,7 +30,9 @@ export default function ({ getService }: FtrProviderContext) {
const alertingApi = getService('alertingApi');
const dataViewApi = getService('dataViewApi');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
describe('Custom Threshold rule - CUSTOM_EQ - AVG - BYTES - FIRED', () => {
const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default';
@ -44,6 +47,7 @@ export default function ({ getService }: FtrProviderContext) {
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
dataForgeConfig = {
schedule: [
{
@ -74,14 +78,8 @@ export default function ({ getService }: FtrProviderContext) {
});
after(async () => {
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/actions/connector/${actionId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: CUSTOM_THRESHOLD_RULE_ALERT_INDEX,
query: { term: { 'kibana.alert.rule.uuid': ruleId } },
@ -241,9 +239,10 @@ export default function ({ getService }: FtrProviderContext) {
docCountTarget: 1,
});
const { protocol, hostname, port } = kbnTestConfig.getUrlParts();
expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`http://localhost:5620/app/observability/alerts/${alertId}`
`${protocol}://${hostname}${port ? `:${port}` : ''}/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Custom equation is 1 B, above the threshold of 0.9 B. (duration: 1 min, data view: ${DATA_VIEW})`

View file

@ -13,10 +13,11 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils';
import { parseSearchParams } from '@kbn/share-plugin/common/url_service';
import { omit } from 'lodash';
import { COMPARATORS } from '@kbn/alerting-comparators';
import { kbnTestConfig } from '@kbn/test';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { ISO_DATE_REGEX } from './constants';
import { ActionDocument, LogsExplorerLocatorParsedParams } from './typings';
import { RoleCredentials } from '../../../../shared/services';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
export default function ({ getService }: FtrProviderContext) {
const esClient = getService('es');
@ -26,7 +27,9 @@ export default function ({ getService }: FtrProviderContext) {
const alertingApi = getService('alertingApi');
const dataViewApi = getService('dataViewApi');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
describe('Custom Threshold rule - DOCUMENTS_COUNT - FIRED', () => {
const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default';
@ -42,6 +45,7 @@ export default function ({ getService }: FtrProviderContext) {
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
dataForgeConfig = {
schedule: [
{
@ -75,14 +79,8 @@ export default function ({ getService }: FtrProviderContext) {
});
after(async () => {
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/actions/connector/${actionId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: CUSTOM_THRESHOLD_RULE_ALERT_INDEX,
query: { term: { 'kibana.alert.rule.uuid': ruleId } },
@ -239,9 +237,11 @@ export default function ({ getService }: FtrProviderContext) {
docCountTarget: 1,
});
const { protocol, hostname, port } = kbnTestConfig.getUrlParts();
expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`http://localhost:5620/app/observability/alerts/${alertId}`
`${protocol}://${hostname}${port ? `:${port}` : ''}/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(

View file

@ -20,7 +20,7 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils';
import { COMPARATORS } from '@kbn/alerting-comparators';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { ActionDocument } from './typings';
import { RoleCredentials } from '../../../../shared/services';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
export default function ({ getService }: FtrProviderContext) {
const esClient = getService('es');
@ -29,9 +29,11 @@ export default function ({ getService }: FtrProviderContext) {
const logger = getService('log');
const alertingApi = getService('alertingApi');
const dataViewApi = getService('dataViewApi');
let alertId: string;
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
let alertId: string;
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
describe('Custom Threshold rule - GROUP_BY - FIRED', () => {
const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default';
@ -45,6 +47,7 @@ export default function ({ getService }: FtrProviderContext) {
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
dataForgeConfig = {
schedule: [
{
@ -75,14 +78,8 @@ export default function ({ getService }: FtrProviderContext) {
});
after(async () => {
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/actions/connector/${actionId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: CUSTOM_THRESHOLD_RULE_ALERT_INDEX,
query: { term: { 'kibana.alert.rule.uuid': ruleId } },
@ -123,7 +120,11 @@ export default function ({ getService }: FtrProviderContext) {
timeSize: 1,
timeUnit: 'm',
metrics: [
{ name: 'A', field: 'system.cpu.total.norm.pct', aggType: Aggregators.AVERAGE },
{
name: 'A',
field: 'system.cpu.total.norm.pct',
aggType: Aggregators.AVERAGE,
},
],
},
],
@ -265,7 +266,7 @@ export default function ({ getService }: FtrProviderContext) {
expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`${protocol}://${hostname}:${port}/app/observability/alerts/${alertId}`
`${protocol}://${hostname}${port ? `:${port}` : ''}/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`Average system.cpu.total.norm.pct is 80%, above or equal the threshold of 20%. (duration: 1 min, data view: ${DATA_VIEW}, group: host-0,container-0)`

View file

@ -13,10 +13,11 @@ import { OBSERVABILITY_THRESHOLD_RULE_TYPE_ID } from '@kbn/rule-data-utils';
import { parseSearchParams } from '@kbn/share-plugin/common/url_service';
import { omit } from 'lodash';
import { COMPARATORS } from '@kbn/alerting-comparators';
import { kbnTestConfig } from '@kbn/test';
import { FtrProviderContext } from '../../../ftr_provider_context';
import { ISO_DATE_REGEX } from './constants';
import { ActionDocument, LogsExplorerLocatorParsedParams } from './typings';
import { RoleCredentials } from '../../../../shared/services';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
export default function ({ getService }: FtrProviderContext) {
const esClient = getService('es');
@ -25,7 +26,9 @@ export default function ({ getService }: FtrProviderContext) {
const alertingApi = getService('alertingApi');
const logger = getService('log');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
describe('Custom Threshold rule - P99 - PCT - FIRED', () => {
const CUSTOM_THRESHOLD_RULE_ALERT_INDEX = '.alerts-observability.threshold.alerts-default';
@ -52,6 +55,7 @@ export default function ({ getService }: FtrProviderContext) {
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
dataForgeConfig = {
schedule: [
{
@ -77,14 +81,8 @@ export default function ({ getService }: FtrProviderContext) {
});
after(async () => {
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/actions/connector/${actionId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: CUSTOM_THRESHOLD_RULE_ALERT_INDEX,
query: { term: { 'kibana.alert.rule.uuid': ruleId } },
@ -238,9 +236,10 @@ export default function ({ getService }: FtrProviderContext) {
docCountTarget: 1,
});
const { protocol, hostname, port } = kbnTestConfig.getUrlParts();
expect(resp.hits.hits[0]._source?.ruleType).eql('observability.rules.custom_threshold');
expect(resp.hits.hits[0]._source?.alertDetailsUrl).eql(
`http://localhost:5620/app/observability/alerts/${alertId}`
`${protocol}://${hostname}${port ? `:${port}` : ''}/app/observability/alerts/${alertId}`
);
expect(resp.hits.hits[0]._source?.reason).eql(
`99th percentile of system.cpu.user.pct is 250%, above the threshold of 50%. (duration: 5 mins, data view: ${DATA_VIEW_NAME})`

View file

@ -11,6 +11,7 @@ import type { APIClientRequestParamsOf, APIReturnType } from '@kbn/dataset-quali
import { Config, kbnTestConfig, kibanaTestSuperuserServerless } from '@kbn/test';
import type { APIEndpoint } from '@kbn/dataset-quality-plugin/server/routes';
import { formatRequest } from '@kbn/server-route-repository';
import { InternalRequestHeader, RoleCredentials } from '../../../../../shared/services';
import { InheritedFtrProviderContext } from '../../../../services';
export function createDatasetQualityApiClient(st: supertest.Agent) {
@ -18,20 +19,18 @@ export function createDatasetQualityApiClient(st: supertest.Agent) {
options: {
type?: 'form-data';
endpoint: TEndpoint;
roleAuthc: RoleCredentials;
internalReqHeader: InternalRequestHeader;
} & APIClientRequestParamsOf<TEndpoint> & { params?: { query?: { _inspect?: boolean } } }
): Promise<SupertestReturnType<TEndpoint>> => {
const { endpoint, type } = options;
const { endpoint, type, internalReqHeader, roleAuthc } = options;
const params = 'params' in options ? (options.params as Record<string, any>) : {};
const { method, pathname, version } = formatRequest(endpoint, params.path);
const url = format({ pathname, query: params?.query });
const headers: Record<string, string> = {
'kbn-xsrf': 'foo',
'x-elastic-internal-origin': 'foo',
};
const headers: Record<string, string> = { ...internalReqHeader, ...roleAuthc.apiKeyHeader };
if (version) {
headers['Elastic-Api-Version'] = version;
}

View file

@ -7,6 +7,7 @@
import { log, timerange } from '@kbn/apm-synthtrace-client';
import expect from '@kbn/expect';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
import { expectToReject } from './utils';
import {
DatasetQualityApiClient,
@ -17,6 +18,8 @@ import { DatasetQualityFtrContextProvider } from './common/services';
export default function ({ getService }: DatasetQualityFtrContextProvider) {
const datasetQualityApiClient: DatasetQualityApiClient = getService('datasetQualityApiClient');
const synthtrace = getService('logSynthtraceEsClient');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
const start = '2023-12-11T18:00:00.000Z';
const end = '2023-12-11T18:01:00.000Z';
const type = 'logs';
@ -25,7 +28,11 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
const serviceName = 'my-service';
const hostName = 'synth-host';
async function callApi(dataStream: string) {
async function callApi(
dataStream: string,
roleAuthc: RoleCredentials,
internalReqHeader: InternalRequestHeader
) {
return await datasetQualityApiClient.slsUser({
endpoint: 'GET /internal/dataset_quality/data_streams/{dataStream}/details',
params: {
@ -37,12 +44,19 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
end,
},
},
roleAuthc,
internalReqHeader,
});
}
describe('gets the data stream details', () => {
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
before(async () => {
await synthtrace.index([
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
return synthtrace.index([
timerange(start, end)
.interval('1m')
.rate(1)
@ -61,11 +75,14 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
),
]);
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('returns error when dataStream param is not provided', async () => {
const expectedMessage = 'Data Stream name cannot be empty';
const err = await expectToReject<DatasetQualityApiError>(() =>
callApi(encodeURIComponent(' '))
callApi(encodeURIComponent(' '), roleAuthc, internalReqHeader)
);
expect(err.res.status).to.be(400);
expect(err.res.body.message.indexOf(expectedMessage)).to.greaterThan(-1);
@ -74,17 +91,17 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
it('returns {} if matching data stream is not available', async () => {
const nonExistentDataSet = 'Non-existent';
const nonExistentDataStream = `${type}-${nonExistentDataSet}-${namespace}`;
const resp = await callApi(nonExistentDataStream);
const resp = await callApi(nonExistentDataStream, roleAuthc, internalReqHeader);
expect(resp.body).empty();
});
it('returns "sizeBytes" as null in serverless', async () => {
const resp = await callApi(`${type}-${dataset}-${namespace}`);
const resp = await callApi(`${type}-${dataset}-${namespace}`, roleAuthc, internalReqHeader);
expect(resp.body.sizeBytes).to.be(null);
});
it('returns service.name and host.name correctly', async () => {
const resp = await callApi(`${type}-${dataset}-${namespace}`);
const resp = await callApi(`${type}-${dataset}-${namespace}`, roleAuthc, internalReqHeader);
expect(resp.body.services).to.eql({ ['service.name']: [serviceName] });
expect(resp.body.hosts?.['host.name']).to.eql([hostName]);
});

View file

@ -7,6 +7,7 @@
import { log, timerange } from '@kbn/apm-synthtrace-client';
import expect from '@kbn/expect';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
import { expectToReject, getDataStreamSettingsOfEarliestIndex, rolloverDataStream } from './utils';
import {
DatasetQualityApiClient,
@ -17,6 +18,8 @@ import { DatasetQualityFtrContextProvider } from './common/services';
export default function ({ getService }: DatasetQualityFtrContextProvider) {
const datasetQualityApiClient: DatasetQualityApiClient = getService('datasetQualityApiClient');
const synthtrace = getService('logSynthtraceEsClient');
const svlCommonApi = getService('svlCommonApi');
const svlUserManager = getService('svlUserManager');
const esClient = getService('es');
const start = '2023-12-11T18:00:00.000Z';
const end = '2023-12-11T18:01:00.000Z';
@ -26,7 +29,11 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
const serviceName = 'my-service';
const hostName = 'synth-host';
async function callApi(dataStream: string) {
async function callApi(
dataStream: string,
roleAuthc: RoleCredentials,
internalReqHeader: InternalRequestHeader
) {
return await datasetQualityApiClient.slsUser({
endpoint: 'GET /internal/dataset_quality/data_streams/{dataStream}/settings',
params: {
@ -34,12 +41,18 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
dataStream,
},
},
roleAuthc,
internalReqHeader,
});
}
describe('gets the data stream settings', () => {
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
before(async () => {
await synthtrace.index([
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
return synthtrace.index([
timerange(start, end)
.interval('1m')
.rate(1)
@ -59,10 +72,14 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
]);
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('returns error when dataStream param is not provided', async () => {
const expectedMessage = 'Data Stream name cannot be empty';
const err = await expectToReject<DatasetQualityApiError>(() =>
callApi(encodeURIComponent(' '))
callApi(encodeURIComponent(' '), roleAuthc, internalReqHeader)
);
expect(err.res.status).to.be(400);
expect(err.res.body.message.indexOf(expectedMessage)).to.greaterThan(-1);
@ -71,7 +88,7 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
it('returns {} if matching data stream is not available', async () => {
const nonExistentDataSet = 'Non-existent';
const nonExistentDataStream = `${type}-${nonExistentDataSet}-${namespace}`;
const resp = await callApi(nonExistentDataStream);
const resp = await callApi(nonExistentDataStream, roleAuthc, internalReqHeader);
expect(resp.body).empty();
});
@ -80,7 +97,7 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
esClient,
`${type}-${dataset}-${namespace}`
);
const resp = await callApi(`${type}-${dataset}-${namespace}`);
const resp = await callApi(`${type}-${dataset}-${namespace}`, roleAuthc, internalReqHeader);
expect(resp.body.createdOn).to.be(Number(dataStreamSettings?.index?.creation_date));
});
@ -90,7 +107,7 @@ export default function ({ getService }: DatasetQualityFtrContextProvider) {
esClient,
`${type}-${dataset}-${namespace}`
);
const resp = await callApi(`${type}-${dataset}-${namespace}`);
const resp = await callApi(`${type}-${dataset}-${namespace}`, roleAuthc, internalReqHeader);
expect(resp.body.createdOn).to.be(Number(dataStreamSettings?.index?.creation_date));
});

View file

@ -38,14 +38,9 @@ export default function ({ getService }: FtrProviderContext) {
});
after(async () => {
await supertest
.delete(`/api/alerting/rule/${ruleId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest
.delete(`/api/actions/connector/${actionId}`)
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
await supertest.delete(`/api/alerting/rule/${ruleId}`).set(internalReqHeader);
await supertest.delete(`/api/actions/connector/${actionId}`).set(internalReqHeader);
await esClient.deleteByQuery({
index: '.kibana-event-log-*',
query: { term: { 'rule.id': ruleId } },

View file

@ -6,6 +6,7 @@
*/
import expect from 'expect';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
import {
expectDefaultElasticsearchOutput,
@ -14,24 +15,35 @@ import {
export default function (ctx: FtrProviderContext) {
const svlCommonApi = ctx.getService('svlCommonApi');
const supertest = ctx.getService('supertest');
const svlUserManager = ctx.getService('svlUserManager');
const supertestWithoutAuth = ctx.getService('supertestWithoutAuth');
describe('fleet', function () {
let defaultFleetServerHostUrl: string = '';
let defaultEsOutputUrl: string = '';
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
before(async () => {
internalReqHeader = svlCommonApi.getInternalRequestHeader();
defaultFleetServerHostUrl = await expectDefaultFleetServer(ctx);
expect(defaultFleetServerHostUrl).not.toBe('');
defaultEsOutputUrl = await expectDefaultElasticsearchOutput(ctx);
expect(defaultEsOutputUrl).not.toBe('');
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('rejects request to create a new fleet server hosts if host url is different from default', async () => {
const { body, status } = await supertest
const { body, status } = await supertestWithoutAuth
.post('/api/fleet/fleet_server_hosts')
.set(svlCommonApi.getInternalRequestHeader())
.set(internalReqHeader)
.set(roleAuthc.apiKeyHeader)
.send({
name: 'test',
host_urls: ['https://localhost:8221'],
@ -47,9 +59,10 @@ export default function (ctx: FtrProviderContext) {
});
it('accepts request to create a new fleet server hosts if host url is same as default', async () => {
const { body, status } = await supertest
const { body, status } = await supertestWithoutAuth
.post('/api/fleet/fleet_server_hosts')
.set(svlCommonApi.getInternalRequestHeader())
.set(internalReqHeader)
.set(roleAuthc.apiKeyHeader)
.send({
name: 'Test Fleet server host',
host_urls: [defaultFleetServerHostUrl],
@ -65,9 +78,10 @@ export default function (ctx: FtrProviderContext) {
});
it('rejects request to create a new elasticsearch output if host is different from default', async () => {
const { body, status } = await supertest
const { body, status } = await supertestWithoutAuth
.post('/api/fleet/outputs')
.set(svlCommonApi.getInternalRequestHeader())
.set(internalReqHeader)
.set(roleAuthc.apiKeyHeader)
.send({
name: 'Test output',
type: 'elasticsearch',
@ -83,9 +97,10 @@ export default function (ctx: FtrProviderContext) {
});
it('accepts request to create a new elasticsearch output if host url is same as default', async () => {
const { body, status } = await supertest
const { body, status } = await supertestWithoutAuth
.post('/api/fleet/outputs')
.set(svlCommonApi.getInternalRequestHeader())
.set(internalReqHeader)
.set(roleAuthc.apiKeyHeader)
.send({
name: 'Test output',
type: 'elasticsearch',

View file

@ -10,8 +10,7 @@ import type {
GetInfraMetricsRequestBodyPayload,
GetInfraMetricsResponsePayload,
} from '@kbn/infra-plugin/common/http_api';
import { kbnTestConfig, kibanaTestSuperuserServerless } from '@kbn/test';
import type { RoleCredentials } from '../../../../shared/services';
import type { FtrProviderContext } from '../../../ftr_provider_context';
import { DATES, ARCHIVE_NAME } from './constants';
@ -23,67 +22,77 @@ const timeRange = {
export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
const username = kbnTestConfig.getUrlParts(kibanaTestSuperuserServerless).username || '';
const password = kbnTestConfig.getUrlParts(kibanaTestSuperuserServerless).password || '';
const supertestWithoutAuth = getService('supertestWithoutAuth');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
const fetchInfraHosts = async (
body: GetInfraMetricsRequestBodyPayload
body: GetInfraMetricsRequestBodyPayload,
roleAuthc: RoleCredentials
): Promise<GetInfraMetricsResponsePayload | undefined> => {
const response = await supertest
const response = await supertestWithoutAuth
.post('/api/metrics/infra')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.auth(username, password)
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.send(body)
.expect(200);
return response.body;
};
describe('API /metrics/infra', () => {
let roleAuthc: RoleCredentials;
describe('works', () => {
describe('with host asset', () => {
before(async () => esArchiver.load(ARCHIVE_NAME));
after(async () => esArchiver.unload(ARCHIVE_NAME));
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
return esArchiver.load(ARCHIVE_NAME);
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
return esArchiver.unload(ARCHIVE_NAME);
});
it('received data', async () => {
const infraHosts = await fetchInfraHosts({
type: 'host',
limit: 100,
metrics: [
{
type: 'rx',
const infraHosts = await fetchInfraHosts(
{
type: 'host',
limit: 100,
metrics: [
{
type: 'rx',
},
{
type: 'tx',
},
{
type: 'memory',
},
{
type: 'cpu',
},
{
type: 'diskSpaceUsage',
},
{
type: 'memoryFree',
},
],
query: {
bool: {
must: [],
filter: [],
should: [],
must_not: [],
},
},
{
type: 'tx',
},
{
type: 'memory',
},
{
type: 'cpu',
},
{
type: 'diskSpaceUsage',
},
{
type: 'memoryFree',
},
],
query: {
bool: {
must: [],
filter: [],
should: [],
must_not: [],
range: {
from: timeRange.from,
to: timeRange.to,
},
sourceId: 'default',
},
range: {
from: timeRange.from,
to: timeRange.to,
},
sourceId: 'default',
});
roleAuthc
);
if (infraHosts) {
const { nodes } = infraHosts;

View file

@ -10,7 +10,7 @@ import type {
InfraMetadata,
InfraMetadataRequest,
} from '@kbn/infra-plugin/common/http_api/metadata_api';
import { kbnTestConfig, kibanaTestSuperuserServerless } from '@kbn/test';
import type { RoleCredentials } from '../../../../shared/services';
import type { FtrProviderContext } from '../../../ftr_provider_context';
import { DATES, ARCHIVE_NAME } from './constants';
@ -22,34 +22,45 @@ const timeRange = {
export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
const username = kbnTestConfig.getUrlParts(kibanaTestSuperuserServerless).username || '';
const password = kbnTestConfig.getUrlParts(kibanaTestSuperuserServerless).password || '';
const supertestWithoutAuth = getService('supertestWithoutAuth');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
const fetchMetadata = async (body: InfraMetadataRequest): Promise<InfraMetadata | undefined> => {
const response = await supertest
const fetchMetadata = async (
body: InfraMetadataRequest,
roleAuthc: RoleCredentials
): Promise<InfraMetadata | undefined> => {
const response = await supertestWithoutAuth
.post('/api/infra/metadata')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.auth(username, password)
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.send(body)
.expect(200);
return response.body;
};
describe('API /infra/metadata', () => {
let roleAuthc: RoleCredentials;
describe('works', () => {
describe('Host asset type', () => {
before(async () => esArchiver.load(ARCHIVE_NAME));
after(async () => esArchiver.unload(ARCHIVE_NAME));
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
await esArchiver.load(ARCHIVE_NAME);
});
after(async () => {
await esArchiver.unload(ARCHIVE_NAME);
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('with serverless existing host', async () => {
const metadata = await fetchMetadata({
sourceId: 'default',
nodeId: 'serverless-host',
nodeType: 'host',
timeRange,
});
const metadata = await fetchMetadata(
{
sourceId: 'default',
nodeId: 'serverless-host',
nodeType: 'host',
timeRange,
},
roleAuthc
);
if (metadata) {
expect(metadata.features.length).to.be(4);

View file

@ -11,27 +11,33 @@ import {
ProcessListAPIResponseRT,
} from '@kbn/infra-plugin/common/http_api/host_details/process_list';
import { decodeOrThrow } from '@kbn/infra-plugin/common/runtime_types';
import { kbnTestConfig, kibanaTestSuperuserServerless } from '@kbn/test';
import type { RoleCredentials } from '../../../../shared/services';
import type { FtrProviderContext } from '../../../ftr_provider_context';
import { DATES, ARCHIVE_NAME } from './constants';
export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
describe('API /metrics/process_list', () => {
const username = kbnTestConfig.getUrlParts(kibanaTestSuperuserServerless).username || '';
const password = kbnTestConfig.getUrlParts(kibanaTestSuperuserServerless).password || '';
before(async () => esArchiver.load(ARCHIVE_NAME));
after(async () => esArchiver.unload(ARCHIVE_NAME));
let roleAuthc: RoleCredentials;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
await esArchiver.load(ARCHIVE_NAME);
});
after(async () => {
await esArchiver.unload(ARCHIVE_NAME);
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('works', async () => {
const response = await supertest
const response = await supertestWithoutAuth
.post('/api/metrics/process_list')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.auth(username, password)
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.send(
ProcessListAPIRequestRT.encode({
hostTerm: {

View file

@ -10,48 +10,60 @@ import type {
SnapshotNodeResponse,
SnapshotRequest,
} from '@kbn/infra-plugin/common/http_api/snapshot_api';
import { kbnTestConfig, kibanaTestSuperuserServerless } from '@kbn/test';
import type { RoleCredentials } from '../../../../shared/services';
import type { FtrProviderContext } from '../../../ftr_provider_context';
import { DATES, ARCHIVE_NAME } from './constants';
export default function ({ getService }: FtrProviderContext) {
const esArchiver = getService('esArchiver');
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
const fetchSnapshot = async (
body: SnapshotRequest
body: SnapshotRequest,
roleAuthc: RoleCredentials
): Promise<SnapshotNodeResponse | undefined> => {
const username = kbnTestConfig.getUrlParts(kibanaTestSuperuserServerless).username || '';
const password = kbnTestConfig.getUrlParts(kibanaTestSuperuserServerless).password || '';
const response = await supertest
const response = await supertestWithoutAuth
.post('/api/metrics/snapshot')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.auth(username, password)
.set(svlCommonApi.getInternalRequestHeader())
.set(roleAuthc.apiKeyHeader)
.send(body)
.expect(200);
return response.body;
};
describe('API /metrics/snapshot', () => {
let roleAuthc: RoleCredentials;
describe('Snapshot nodes', () => {
const { min, max } = DATES.serverlessTestingHost;
before(async () => esArchiver.load(ARCHIVE_NAME));
after(async () => esArchiver.unload(ARCHIVE_NAME));
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
await esArchiver.load(ARCHIVE_NAME);
});
after(async () => {
await esArchiver.unload(ARCHIVE_NAME);
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('should work', async () => {
const snapshot = await fetchSnapshot({
sourceId: 'default',
timerange: {
to: max,
from: min,
interval: '10m',
const snapshot = await fetchSnapshot(
{
sourceId: 'default',
timerange: {
to: max,
from: min,
interval: '10m',
},
metrics: [{ type: 'cpu' }],
nodeType: 'host',
groupBy: [],
includeTimeseries: false,
},
metrics: [{ type: 'cpu' }],
nodeType: 'host',
groupBy: [],
includeTimeseries: false,
});
roleAuthc
);
if (!snapshot) {
return;

View file

@ -15,6 +15,7 @@ import {
getSLOSummaryPipelineId,
SLO_SUMMARY_TEMP_INDEX_NAME,
} from '@kbn/slo-plugin/common/constants';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
interface ExpectedTransforms {
@ -50,6 +51,8 @@ export default function ({ getService }: FtrProviderContext) {
const sloApi = getService('sloApi');
const kibanaServer = getService('kibanaServer');
const transform = getService('transform');
const svlUserManager = getService('svlUserManager');
const svlCommonApi = getService('svlCommonApi');
describe('create_slo', () => {
// DATE_VIEW should match the index template:
@ -57,6 +60,7 @@ export default function ({ getService }: FtrProviderContext) {
const DATE_VIEW = 'kbn-data-forge-fake_hosts';
const DATA_VIEW_ID = 'data-view-id';
let infraDataIndex: string;
let roleAuthc: RoleCredentials;
before(async () => {
infraDataIndex = await generate({
@ -70,6 +74,7 @@ export default function ({ getService }: FtrProviderContext) {
title: DATE_VIEW,
});
await kibanaServer.savedObjects.cleanStandardList();
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
@ -78,57 +83,57 @@ export default function ({ getService }: FtrProviderContext) {
});
await supertest
.delete('/api/observability/slos/my-custom-id1')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
.set(svlCommonApi.getInternalRequestHeader());
await supertest
.delete('/api/observability/slos/my-custom-id2')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
.set(svlCommonApi.getInternalRequestHeader());
await supertest
.delete('/api/observability/slos/my-custom-id3')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
.set(svlCommonApi.getInternalRequestHeader());
await supertest
.delete('/api/observability/slos/my-custom-id4')
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo');
.set(svlCommonApi.getInternalRequestHeader());
await esDeleteAllIndices([infraDataIndex]);
await cleanup({ esClient, logger });
await kibanaServer.savedObjects.clean({ types: [SO_SLO_TYPE] });
await transform.api.cleanTransformIndices();
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
describe('non partition by SLO', () => {
const sloId = 'my-custom-id1';
before(async () => {
await sloApi.create({
id: sloId,
name: 'my custom name',
description: 'my custom description',
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
await sloApi.create(
{
id: sloId,
name: 'my custom name',
description: 'my custom description',
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
},
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: ALL_VALUE,
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: ALL_VALUE,
});
roleAuthc
);
});
it('saves the SLO definition', async () => {
@ -158,6 +163,7 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.set('elastic-api-version', '1')
.set(roleAuthc.apiKeyHeader)
.send();
transform.api.assertResponseStatusCode(200, status, body);
assertTransformsResponseBody(body, expectedTransforms);
@ -182,7 +188,10 @@ export default function ({ getService }: FtrProviderContext) {
});
it('finds the created SLO', async () => {
const createdSlo = await sloApi.waitForSloCreated({ sloId });
const createdSlo = await sloApi.waitForSloCreated({
sloId,
roleAuthc,
});
expect(createdSlo.id).to.be(sloId);
expect(createdSlo.groupBy).to.be(ALL_VALUE);
});
@ -191,32 +200,38 @@ export default function ({ getService }: FtrProviderContext) {
describe('SLO with long description', () => {
it('creates an SLO with description over 256 characters', async () => {
const sloId = 'my-custom-id2';
await sloApi.create({
id: sloId,
name: 'my super long SLO name and description',
description:
'Lorem Ipsum has been the industry standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. ',
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
await sloApi.create(
{
id: sloId,
name: 'my super long SLO name and description',
description:
'Lorem Ipsum has been the industry standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. ',
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
},
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: '*',
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: '*',
});
roleAuthc
);
const createdSlo = await sloApi.waitForSloCreated({ sloId });
const createdSlo = await sloApi.waitForSloCreated({
sloId,
roleAuthc,
});
expect(createdSlo.id).to.be(sloId);
});
});
@ -224,31 +239,37 @@ export default function ({ getService }: FtrProviderContext) {
describe('SLO with special characters in the description', () => {
it("creates an SLO that has ' character in the description", async () => {
const sloId = 'my-custom-id3';
await sloApi.create({
id: sloId,
name: 'my SLO with weird characters in the description',
description:
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.",
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
await sloApi.create(
{
id: sloId,
name: 'my SLO with weird characters in the description',
description:
"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged.",
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
},
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: '*',
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: '*',
roleAuthc
);
const createdSlo = await sloApi.waitForSloCreated({
sloId,
roleAuthc,
});
const createdSlo = await sloApi.waitForSloCreated({ sloId });
expect(createdSlo.id).to.be(sloId);
});
});
@ -256,30 +277,36 @@ export default function ({ getService }: FtrProviderContext) {
describe('partition by SLO', () => {
it('creates a partition by SLO', async () => {
const sloId = 'my-custom-id4';
await sloApi.create({
id: sloId,
name: 'Group by SLO',
description: 'This is a group by SLO.',
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
await sloApi.create(
{
id: sloId,
name: 'Group by SLO',
description: 'This is a group by SLO.',
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
},
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: 'host.name',
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: 'host.name',
roleAuthc
);
const createdSlo = await sloApi.waitForSloCreated({
sloId,
roleAuthc,
});
const createdSlo = await sloApi.waitForSloCreated({ sloId });
expect(createdSlo.id).to.be(sloId);
expect(createdSlo.groupBy).not.to.be(ALL_VALUE);
expect(createdSlo.groupBy).to.be('host.name');
@ -320,6 +347,7 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'foo')
.set('x-elastic-internal-origin', 'foo')
.set('elastic-api-version', '1')
.set(roleAuthc.apiKeyHeader)
.send();
transform.api.assertResponseStatusCode(200, status, body);
assertTransformsResponseBody(body, expectedTransforms);

View file

@ -18,9 +18,9 @@ import {
SLO_DESTINATION_INDEX_PATTERN,
SLO_SUMMARY_DESTINATION_INDEX_PATTERN,
} from '@kbn/slo-plugin/common/constants';
import { ElasticsearchClient } from '@kbn/core/server';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const esClient = getService('es');
const logger = getService('log');
@ -31,12 +31,9 @@ export default function ({ getService }: FtrProviderContext) {
const esDeleteAllIndices = getService('esDeleteAllIndices');
const dataViewApi = getService('dataViewApi');
const svlUserManager = getService('svlUserManager');
const fetchSloSummaryPipeline = async (
client: ElasticsearchClient,
sloId: string,
sloRevision: number
) => {
const fetchSloSummaryPipeline = async (sloId: string, sloRevision: number) => {
try {
return await esClient.ingest.getPipeline({
id: getSLOSummaryPipelineId(sloId, sloRevision),
@ -55,6 +52,7 @@ export default function ({ getService }: FtrProviderContext) {
const DATA_VIEW_ID = 'data-view-id';
let infraDataIndex: string;
let sloId: string;
let roleAuthc: RoleCredentials;
before(async () => {
await sloApi.deleteAllSLOs();
@ -70,6 +68,7 @@ export default function ({ getService }: FtrProviderContext) {
title: DATE_VIEW,
});
await kibanaServer.savedObjects.cleanStandardList();
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
@ -79,34 +78,38 @@ export default function ({ getService }: FtrProviderContext) {
await sloApi.deleteAllSLOs();
await esDeleteAllIndices([infraDataIndex]);
await cleanup({ esClient, logger });
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
describe('non partition by SLO', () => {
it('deletes the SLO definition, transforms, ingest pipeline and data', async () => {
const createdSlo = await sloApi.create({
name: 'my custom name',
description: 'my custom description',
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
const createdSlo = await sloApi.create(
{
name: 'my custom name',
description: 'my custom description',
indicator: {
type: 'sli.kql.custom',
params: {
index: infraDataIndex,
good: 'system.cpu.total.norm.pct > 1',
total: 'system.cpu.total.norm.pct: *',
timestampField: '@timestamp',
},
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: ALL_VALUE,
},
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.999,
},
groupBy: ALL_VALUE,
});
roleAuthc
);
sloId = createdSlo.id;
await sloApi.waitForSloCreated({ sloId });
await sloApi.waitForSloCreated({ sloId, roleAuthc });
// Saved Object
const savedObject = await kibanaServer.savedObjects.find({
@ -123,7 +126,7 @@ export default function ({ getService }: FtrProviderContext) {
await transform.api.waitForTransformToExist(sloSummaryTransformId);
// Ingest pipeline
const pipelineResponse = await fetchSloSummaryPipeline(esClient, sloId, sloRevision);
const pipelineResponse = await fetchSloSummaryPipeline(sloId, sloRevision);
expect(pipelineResponse[getSLOSummaryPipelineId(sloId, sloRevision)]).not.to.be(undefined);
// RollUp and Summary data
@ -140,7 +143,10 @@ export default function ({ getService }: FtrProviderContext) {
expect(sloSummaryData.hits.hits.length > 0).to.be(true);
// Delete the SLO
const response = await sloApi.waitForSloToBeDeleted(sloId);
const response = await sloApi.waitForSloToBeDeleted({
sloId,
roleAuthc,
});
expect(response.status).to.be(204);
// Saved object definition

View file

@ -13,22 +13,26 @@ import {
import { ALL_VALUE } from '@kbn/slo-schema';
import moment from 'moment';
import { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ getService }: FtrProviderContext) {
const esClient = getService('es');
const esDeleteAllIndices = getService('esDeleteAllIndices');
const sloApi = getService('sloApi');
const svlUserManager = getService('svlUserManager');
const SLO_ID = 'slo-fake-1';
// Failing: See https://github.com/elastic/kibana/issues/183748
describe.skip('fetch historical summary', () => {
describe('fetch historical summary', () => {
let roleAuthc: RoleCredentials;
before(async () => {
const now = moment().startOf('minute');
const curr = now.clone().subtract(30, 'days');
const end = now.clone().add(5, 'minutes');
const batchOperations = [];
while (curr.isSameOrBefore(end)) {
batchOperations.push([
{ index: { _index: SLO_DESTINATION_INDEX_NAME } },
@ -55,31 +59,36 @@ export default function ({ getService }: FtrProviderContext) {
});
await esClient.indices.refresh({ index: SLO_DESTINATION_INDEX_NAME });
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
after(async () => {
await esDeleteAllIndices(SLO_DESTINATION_INDEX_PATTERN);
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('computes the historical summary for a rolling occurrences SLO', async () => {
const response = await sloApi.fetchHistoricalSummary({
list: [
{
sloId: SLO_ID,
instanceId: ALL_VALUE,
timeWindow: {
duration: '7d',
type: 'rolling',
const response = await sloApi.fetchHistoricalSummary(
{
list: [
{
sloId: SLO_ID,
instanceId: ALL_VALUE,
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'occurrences',
objective: {
target: 0.9,
},
groupBy: ALL_VALUE,
revision: 1,
},
budgetingMethod: 'occurrences',
objective: {
target: 0.9,
},
groupBy: ALL_VALUE,
revision: 1,
},
],
});
],
},
roleAuthc
);
expect(response[0].sloId).to.eql(SLO_ID);
expect(response[0].instanceId).to.eql(ALL_VALUE);
const numberOfBuckets = response[0].data.length;
@ -96,26 +105,29 @@ export default function ({ getService }: FtrProviderContext) {
});
it('computes the historical summary for a rolling timeslices SLO', async () => {
const response = await sloApi.fetchHistoricalSummary({
list: [
{
sloId: SLO_ID,
instanceId: ALL_VALUE,
timeWindow: {
duration: '7d',
type: 'rolling',
const response = await sloApi.fetchHistoricalSummary(
{
list: [
{
sloId: SLO_ID,
instanceId: ALL_VALUE,
timeWindow: {
duration: '7d',
type: 'rolling',
},
budgetingMethod: 'timeslices',
objective: {
target: 0.9,
timesliceTarget: 0.8,
timesliceWindow: '1m',
},
groupBy: ALL_VALUE,
revision: 1,
},
budgetingMethod: 'timeslices',
objective: {
target: 0.9,
timesliceTarget: 0.8,
timesliceWindow: '1m',
},
groupBy: ALL_VALUE,
revision: 1,
},
],
});
],
},
roleAuthc
);
expect(response[0].sloId).to.eql(SLO_ID);
expect(response[0].instanceId).to.eql(ALL_VALUE);
const numberOfBuckets = response[0].data.length;

View file

@ -12,19 +12,29 @@ import xpackRootTelemetrySchema from '@kbn/telemetry-collection-xpack-plugin/sch
import ossPluginsTelemetrySchema from '@kbn/telemetry-plugin/schema/oss_plugins.json';
import xpackPluginsTelemetrySchema from '@kbn/telemetry-collection-xpack-plugin/schema/xpack_plugins.json';
import { assertTelemetryPayload } from '@kbn/telemetry-tools';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
import type { UsageStatsPayloadTestFriendly } from '../../../../../test/api_integration/services/usage_api';
export default function ({ getService }: FtrProviderContext) {
const usageApi = getService('usageAPI');
const svlUserManager = getService('svlUserManager');
describe('Snapshot telemetry', function () {
let stats: UsageStatsPayloadTestFriendly;
let roleAuthc: RoleCredentials;
before(async () => {
const [unencryptedPayload] = await usageApi.getTelemetryStats({ unencrypted: true });
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
const [unencryptedPayload] = await usageApi.getTelemetryStats(
{ unencrypted: true },
{ authHeader: roleAuthc.apiKeyHeader }
);
stats = unencryptedPayload.stats;
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('should pass the schema validation (ensures BWC with Classic offering)', () => {
const root = deepmerge(ossRootTelemetrySchema, xpackRootTelemetrySchema);
@ -39,7 +49,10 @@ export default function ({ getService }: FtrProviderContext) {
});
it('includes the serverless info in the body', async () => {
const [unencryptedPayload] = await usageApi.getTelemetryStats({ unencrypted: true });
const [unencryptedPayload] = await usageApi.getTelemetryStats(
{ unencrypted: true },
{ authHeader: roleAuthc.apiKeyHeader }
);
expect(
unencryptedPayload.stats.stack_stats.kibana?.plugins?.telemetry?.labels?.serverless

View file

@ -6,15 +6,15 @@
*/
import { expect } from 'expect';
import type { InternalRequestHeader, RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default function telemetryConfigTest({ getService }: FtrProviderContext) {
const svlCommonApi = getService('svlCommonApi');
const supertest = getService('supertest');
const svlUserManager = getService('svlUserManager');
const supertestWithoutAuth = getService('supertestWithoutAuth');
// failsOnMKI, see https://github.com/elastic/kibana/issues/180348
describe('/api/telemetry/v2/config API Telemetry config', function () {
this.tags(['failsOnMKI']);
const baseConfig = {
allowChangingOptInStatus: false,
optIn: true,
@ -24,34 +24,49 @@ export default function telemetryConfigTest({ getService }: FtrProviderContext)
serverless: 'observability',
},
};
let roleAuthc: RoleCredentials;
let internalReqHeader: InternalRequestHeader;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
internalReqHeader = svlCommonApi.getInternalRequestHeader();
});
after(async () => {
await svlUserManager.invalidateApiKeyForRole(roleAuthc);
});
it('GET should get the default config', async () => {
const { body } = await supertest
const { body } = await supertestWithoutAuth
.get('/api/telemetry/v2/config')
.set(svlCommonApi.getCommonRequestHeader())
.set(internalReqHeader)
.set(roleAuthc.apiKeyHeader)
.expect(200);
expect(body).toMatchObject(baseConfig);
});
// coreApp.allowDynamicConfigOverrides is disabled
it.skip('GET should get updated labels after dynamically updating them', async () => {
await supertest
await supertestWithoutAuth
.put('/internal/core/_settings')
.set(svlCommonApi.getInternalRequestHeader())
.set(internalReqHeader)
.set(roleAuthc.apiKeyHeader)
.set('elastic-api-version', '1')
.send({ 'telemetry.labels.journeyName': 'my-ftr-test' })
.expect(200, { ok: true });
await supertest
const response = await supertestWithoutAuth
.get('/api/telemetry/v2/config')
.set(svlCommonApi.getCommonRequestHeader())
.expect(200, {
...baseConfig,
labels: {
...baseConfig.labels,
journeyName: 'my-ftr-test',
},
});
.set(internalReqHeader)
.set(roleAuthc.apiKeyHeader);
expect(response.status).toBe(200);
expect(response.body).toEqual({
...baseConfig,
labels: expect.objectContaining({
...baseConfig.labels,
journeyName: 'my-ftr-test',
}),
});
});
});
}

View file

@ -6,19 +6,23 @@
*/
import expect from '@kbn/expect';
import { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default ({ getService }: FtrProviderContext): void => {
const svlCases = getService('svlCases');
const svlUserManager = getService('svlUserManager');
let findCasesResp: any;
let postCaseReq: any;
describe('find_cases', () => {
let roleAuthc: RoleCredentials;
describe('basic tests', () => {
before(async () => {
findCasesResp = svlCases.api.getFindCasesResp();
postCaseReq = svlCases.api.getPostCaseReq('securitySolution');
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
afterEach(async () => {
@ -26,16 +30,16 @@ export default ({ getService }: FtrProviderContext): void => {
});
it('should return empty response', async () => {
const cases = await svlCases.api.findCases({});
const cases = await svlCases.api.findCases({}, roleAuthc);
expect(cases).to.eql(findCasesResp);
});
it('should return cases', async () => {
const a = await svlCases.api.createCase(postCaseReq);
const b = await svlCases.api.createCase(postCaseReq);
const c = await svlCases.api.createCase(postCaseReq);
const a = await svlCases.api.createCase(postCaseReq, roleAuthc);
const b = await svlCases.api.createCase(postCaseReq, roleAuthc);
const c = await svlCases.api.createCase(postCaseReq, roleAuthc);
const cases = await svlCases.api.findCases({});
const cases = await svlCases.api.findCases({}, roleAuthc);
expect(cases).to.eql({
...findCasesResp,
@ -46,14 +50,17 @@ export default ({ getService }: FtrProviderContext): void => {
});
it('returns empty response when trying to find cases with owner as cases', async () => {
const cases = await svlCases.api.findCases({ query: { owner: 'cases' } });
const cases = await svlCases.api.findCases({ query: { owner: 'cases' } }, roleAuthc);
expect(cases).to.eql(findCasesResp);
});
it('returns empty response when trying to find cases with owner as observability', async () => {
const cases = await svlCases.api.findCases({
query: { owner: 'observability' },
});
const cases = await svlCases.api.findCases(
{
query: { owner: 'observability' },
},
roleAuthc
);
expect(cases).to.eql(findCasesResp);
});
});

View file

@ -6,27 +6,41 @@
*/
import expect from '@kbn/expect';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default ({ getService }: FtrProviderContext): void => {
const svlCases = getService('svlCases');
const svlUserManager = getService('svlUserManager');
describe('get_case', () => {
let roleAuthc: RoleCredentials;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
afterEach(async () => {
await svlCases.api.deleteCases();
});
it('should return a case', async () => {
const postedCase = await svlCases.api.createCase(
svlCases.api.getPostCaseRequest('securitySolution')
svlCases.api.getPostCaseRequest('securitySolution'),
roleAuthc
);
const theCase = await svlCases.api.getCase(
{
caseId: postedCase.id,
includeComments: true,
},
roleAuthc
);
const theCase = await svlCases.api.getCase({
caseId: postedCase.id,
includeComments: true,
});
const data = svlCases.omit.removeServerGeneratedPropertiesFromCase(theCase);
expect(data).to.eql(svlCases.api.postCaseResp('securitySolution'));
const { created_by: createdBy, ...data } =
svlCases.omit.removeServerGeneratedPropertiesFromCase(theCase);
const { created_by: _, ...expectedData } = svlCases.api.postCaseResp('securitySolution');
expect(data).to.eql(expectedData);
expect(createdBy).to.have.keys('full_name', 'email', 'username');
expect(data.comments?.length).to.eql(0);
});
});

View file

@ -7,44 +7,44 @@
import expect from '@kbn/expect';
import { ConnectorTypes } from '@kbn/cases-plugin/common/types/domain';
import type { RoleCredentials } from '../../../../shared/services';
import { FtrProviderContext } from '../../../ftr_provider_context';
export default ({ getService }: FtrProviderContext): void => {
const svlCases = getService('svlCases');
const svlUserManager = getService('svlUserManager');
describe('post_case', () => {
let roleAuthc: RoleCredentials;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
});
afterEach(async () => {
await svlCases.api.deleteCases();
});
it('should create a case', async () => {
const postedCase = await svlCases.api.createCase(
svlCases.api.getPostCaseRequest('securitySolution', {
connector: {
id: '123',
name: 'Jira',
type: ConnectorTypes.jira,
fields: { issueType: 'Task', priority: 'High', parent: null },
},
})
);
const data = svlCases.omit.removeServerGeneratedPropertiesFromCase(postedCase);
const payload = svlCases.api.getPostCaseRequest('securitySolution', {
connector: {
id: '123',
name: 'Jira',
type: ConnectorTypes.jira,
fields: { issueType: 'Task', priority: 'High', parent: null },
},
});
const postedCase = await svlCases.api.createCase(payload, roleAuthc);
expect(data).to.eql(
svlCases.api.postCaseResp(
'securitySolution',
null,
svlCases.api.getPostCaseRequest('securitySolution', {
connector: {
id: '123',
name: 'Jira',
type: ConnectorTypes.jira,
fields: { issueType: 'Task', priority: 'High', parent: null },
},
})
)
const { created_by: createdBy, ...data } =
svlCases.omit.removeServerGeneratedPropertiesFromCase(postedCase);
const { created_by: _, ...expected } = svlCases.api.postCaseResp(
'securitySolution',
null,
payload
);
expect(data).to.eql(expected);
expect(createdBy).to.have.keys('full_name', 'email', 'username');
});
it('should throw 403 when trying to create a case with observability as owner', async () => {
@ -53,6 +53,7 @@ export default ({ getService }: FtrProviderContext): void => {
svlCases.api.getPostCaseRequest('securitySolution', {
owner: 'observability',
}),
roleAuthc,
403
)
);
@ -64,6 +65,7 @@ export default ({ getService }: FtrProviderContext): void => {
svlCases.api.getPostCaseRequest('securitySolution', {
owner: 'cases',
}),
roleAuthc,
403
)
);

View file

@ -6,6 +6,7 @@
*/
import { OBSERVABILITY_OWNER } from '@kbn/cases-plugin/common';
import type { RoleCredentials } from '../../../../../../shared/services';
import { FtrProviderContext } from '../../../../../ftr_provider_context';
import { navigateToCasesApp } from '../../../../../../shared/lib/cases';
@ -16,18 +17,22 @@ export default function ({ getPageObject, getPageObjects, getService }: FtrProvi
const svlCommonScreenshots = getService('svlCommonScreenshots');
const screenshotDirectories = ['response_ops_docs', 'observability_cases'];
const testSubjects = getService('testSubjects');
const svlUserManager = getService('svlUserManager');
const owner = OBSERVABILITY_OWNER;
let caseIdMonitoring: string;
describe('list view', function () {
let roleAuthc: RoleCredentials;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
await svlCases.api.createCase(
svlCases.api.getPostCaseRequest(owner, {
title: 'Metrics inventory',
tags: ['IBM resilient'],
description: 'Test.',
owner,
})
}),
roleAuthc
);
await svlCases.api.createCase(
@ -36,7 +41,8 @@ export default function ({ getPageObject, getPageObjects, getService }: FtrProvi
tags: ['jira'],
description: 'Test.',
owner,
})
}),
roleAuthc
);
const caseMonitoring = await svlCases.api.createCase(
@ -45,7 +51,8 @@ export default function ({ getPageObject, getPageObjects, getService }: FtrProvi
tags: ['swimlane'],
description: 'Test.',
owner,
})
}),
roleAuthc
);
caseIdMonitoring = caseMonitoring.id;
});

View file

@ -7,6 +7,7 @@
import { SECURITY_SOLUTION_OWNER } from '@kbn/cases-plugin/common';
import { CaseSeverity } from '@kbn/cases-plugin/common/types/domain';
import type { RoleCredentials } from '../../../../../../shared/services';
import { FtrProviderContext } from '../../../../../ftr_provider_context';
import { navigateToCasesApp } from '../../../../../../shared/lib/cases';
@ -17,11 +18,14 @@ export default function ({ getPageObject, getPageObjects, getService }: FtrProvi
const svlCommonScreenshots = getService('svlCommonScreenshots');
const screenshotDirectories = ['response_ops_docs', 'security_cases'];
const testSubjects = getService('testSubjects');
const svlUserManager = getService('svlUserManager');
const owner = SECURITY_SOLUTION_OWNER;
let caseIdSuspiciousEmail: string;
describe('list view', function () {
let roleAuthc: RoleCredentials;
before(async () => {
roleAuthc = await svlUserManager.createApiKeyForRole('admin');
await svlCases.api.createCase(
svlCases.api.getPostCaseRequest(owner, {
title: 'Unusual processes identified',
@ -29,7 +33,8 @@ export default function ({ getPageObject, getPageObjects, getService }: FtrProvi
description: 'Test.',
owner,
severity: CaseSeverity.HIGH,
})
}),
roleAuthc
);
const caseSuspiciousEmail = await svlCases.api.createCase(
@ -38,7 +43,8 @@ export default function ({ getPageObject, getPageObjects, getService }: FtrProvi
tags: ['email', 'phishing'],
description: 'Several employees have received suspicious emails from an unknown address.',
owner,
})
}),
roleAuthc
);
caseIdSuspiciousEmail = caseSuspiciousEmail.id;
@ -49,7 +55,8 @@ export default function ({ getPageObject, getPageObjects, getService }: FtrProvi
description: 'Test.',
owner,
severity: CaseSeverity.MEDIUM,
})
}),
roleAuthc
);
});