FIPS FTR Overrides and test skips (#192053)

## Summary

Kibana requires security to be enabled and a platinum or better license
to run in FIPS mode.

Since not all FTR configs assume these conditions will be enabled, we
cant run every test. So these failing tests will be skipped when these
overrides are enforced.

This does not mean that the functionality is not supported in FIPS mode.

## What is the point?

Running these tests in FIPS mode is not necessarily to check that the
functionality works as expected, it is to make sure Kibana does not
crash due to unsupported algorithm usage (`md4`, `md5`, etc).

When running in FIPS mode, Node will throw an `unsupported envelope
function` error (with FIPS enabled) if it encounters an unsupported
algorithm, so the more lines of code covered, the more assurance we can
have that features will work in FIPS mode.

## Nature of the changes

To skip a test, a `tag` is added: `this.tags('skipFIPS')`

`this.tags` is only available for `describe('description', function()
{...});`

There should not be any logical changes, just tests wrapped in an extra
block.

I tried to make the wording in the new `describe` block "flow" 😅 if you
prefer different wording in the new `describe` block - please add a
change!

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Nikita Indik <nikita.indik@elastic.co>
This commit is contained in:
Kurt 2024-09-10 13:17:40 -04:00 committed by GitHub
parent 2d40fa3311
commit 5ec0cb0ed2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
103 changed files with 1913 additions and 1589 deletions

View file

@ -135,6 +135,8 @@ export GH_REPO=github.com/elastic/kibana
FTR_ENABLE_FIPS_AGENT=false
if [[ "${KBN_ENABLE_FIPS:-}" == "true" ]] || is_pr_with_label "ci:enable-fips-agent"; then
FTR_ENABLE_FIPS_AGENT=true
ES_SECURITY_ENABLED=true
export ES_SECURITY_ENABLED
# used by FIPS agents to link FIPS OpenSSL modules
export OPENSSL_MODULES=$HOME/openssl/lib/ossl-modules

View file

@ -54,6 +54,18 @@ export class TestUser extends FtrService {
return;
}
/*
* When running in FIPS mode, security must be enabled. Many suites expect that there will be no authc/authz.
* Test user is configured to get `defaultRole` which is being overridden in `fips_overrides.ts` to the most privileged
* roles available so that more tests can be run successfully
*/
if (process.env.FTR_ENABLE_FIPS_AGENT?.toLowerCase() === 'true') {
this.log.debug(
`FTR is running in FIPS mode and does not allow for Test User's roles to be overridden`
);
return;
}
this.log.debug(`set roles = ${roles}`);
await this.user.create(TEST_USER_NAME, {
password: TEST_USER_PASSWORD,
@ -79,7 +91,6 @@ export class TestUser extends FtrService {
export async function createTestUserService(ctx: FtrProviderContext, role: Role, user: User) {
const log = ctx.getService('log');
const config = ctx.getService('config');
const enabled =
!config
.get('esTestCluster.serverArgs')

View file

@ -0,0 +1,46 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/
// This will only apply overrides when running in FIPS mode
export function applyFipsOverrides(vars: any) {
vars.esTestCluster.license = 'trial';
const skipTags = vars.suiteTags?.exclude ?? [];
skipTags.push('skipFIPS');
vars.suiteTags = {
...vars.suiteTags,
exclude: skipTags,
};
vars.security = {
...vars.security,
/*
* When running in FIPS mode, security must be enabled. Many suites expect that there will be no authc/authz.
* Test user's roles are set to `defaultRoles`, the most privileged roles are added here
* so that more tests can be run successfully
*/
defaultRoles: ['superuser', 'kibana_admin', 'system_indices_superuser'],
};
const newServerArgs = vars.esTestCluster.serverArgs.filter(
(arg: string) => arg !== 'xpack.security.enabled=false'
);
newServerArgs.push('xpack.security.enabled=true');
const selfTypedBasicLicenseIndex = newServerArgs.indexOf(
`xpack.license.self_generated.type=basic`
);
if (selfTypedBasicLicenseIndex > -1) {
newServerArgs[selfTypedBasicLicenseIndex] = `xpack.license.self_generated.type=trial`;
}
vars.esTestCluster.serverArgs = newServerArgs;
return vars;
}

View file

@ -14,7 +14,8 @@ import { REPO_ROOT } from '@kbn/repo-info';
import { ToolingLog } from '@kbn/tooling-log';
import { withProcRunner } from '@kbn/dev-proc-runner';
import { readConfigFile } from '../../functional_test_runner';
import { applyFipsOverrides } from '../lib/fips_overrides';
import { Config, readConfigFile } from '../../functional_test_runner';
import { checkForEnabledTestsInFtrConfig, runFtr } from '../lib/run_ftr';
import { runElasticsearch } from '../lib/run_elasticsearch';
@ -68,7 +69,18 @@ export async function runTests(log: ToolingLog, options: RunTestsOptions) {
log.write(`--- [${progress}] Running ${Path.relative(REPO_ROOT, path)}`);
}
const config = await readConfigFile(log, options.esVersion, path, settingOverrides);
let config: Config;
if (process.env.FTR_ENABLE_FIPS_AGENT?.toLowerCase() !== 'true') {
config = await readConfigFile(log, options.esVersion, path, settingOverrides);
} else {
config = await readConfigFile(
log,
options.esVersion,
path,
settingOverrides,
applyFipsOverrides
);
}
const hasTests = await checkForEnabledTestsInFtrConfig({
config,

View file

@ -16,7 +16,8 @@ import { ToolingLog } from '@kbn/tooling-log';
import { withProcRunner } from '@kbn/dev-proc-runner';
import { getTimeReporter } from '@kbn/ci-stats-reporter';
import { readConfigFile } from '../../functional_test_runner';
import { applyFipsOverrides } from '../lib/fips_overrides';
import { Config, readConfigFile } from '../../functional_test_runner';
import { runElasticsearch } from '../lib/run_elasticsearch';
import { runKibanaServer } from '../lib/run_kibana_server';
import { StartServerOptions } from './flags';
@ -28,7 +29,12 @@ export async function startServers(log: ToolingLog, options: StartServerOptions)
const reportTime = getTimeReporter(log, 'scripts/functional_tests_server');
await withProcRunner(log, async (procs) => {
const config = await readConfigFile(log, options.esVersion, options.config);
let config: Config;
if (process.env.FTR_ENABLE_FIPS_AGENT?.toLowerCase() !== 'true') {
config = await readConfigFile(log, options.esVersion, options.config);
} else {
config = await readConfigFile(log, options.esVersion, options.config, {}, applyFipsOverrides);
}
const shutdownEs = await runElasticsearch({
config,

View file

@ -237,7 +237,8 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
});
});
describe('insights', () => {
describe('insights', function () {
this.tags('skipFIPS');
const DASHBOARD_NAME = 'Insights Dashboard';
before(async () => {

View file

@ -88,11 +88,15 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
await testSubjects.missingOrFail('discoverErrorCalloutTitle');
});
it('should not show Patterns tab (basic license)', async () => {
await testSubjects.missingOrFail('dscViewModePatternAnalysisButton');
await retry.try(async () => {
const documentTab = await testSubjects.find('dscViewModeDocumentButton');
expect(await documentTab.getAttribute('aria-selected')).to.be('true');
describe('Patterns tab (basic license)', function () {
this.tags('skipFIPS');
it('should not show', async function () {
await testSubjects.missingOrFail('dscViewModePatternAnalysisButton');
await retry.try(async () => {
const documentTab = await testSubjects.find('dscViewModeDocumentButton');
expect(await documentTab.getAttribute('aria-selected')).to.be('true');
});
});
});

View file

@ -22,6 +22,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const queryBar = getService('queryBar');
describe('discover as defaultRoute', function () {
this.tags('skipFIPS');
before(async function () {
await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']);
await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover');

View file

@ -36,19 +36,22 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const apps = ['dashboards', 'discover', 'canvas', 'maps', 'ml'];
it('should display Analytics apps cards', async () => {
const kbnOverviewAppsCards = await find.allByCssSelector('.kbnOverviewApps__item');
expect(kbnOverviewAppsCards.length).to.be(apps.length);
describe('Analytics apps cards', function () {
this.tags('skipFIPS');
it('should display ', async () => {
const kbnOverviewAppsCards = await find.allByCssSelector('.kbnOverviewApps__item');
expect(kbnOverviewAppsCards.length).to.be(apps.length);
const verifyImageUrl = async (el: WebElementWrapper, imgName: string) => {
const image = await el.findByCssSelector('img');
const imageUrl = (await image.getAttribute('src')) ?? '';
expect(imageUrl.includes(imgName)).to.be(true);
};
const verifyImageUrl = async (el: WebElementWrapper, imgName: string) => {
const image = await el.findByCssSelector('img');
const imageUrl = (await image.getAttribute('src')) ?? '';
expect(imageUrl.includes(imgName)).to.be(true);
};
for (let i = 0; i < apps.length; i++) {
await verifyImageUrl(kbnOverviewAppsCards[i], `kibana_${apps[i]}_light.svg`);
}
for (let i = 0; i < apps.length; i++) {
await verifyImageUrl(kbnOverviewAppsCards[i], `kibana_${apps[i]}_light.svg`);
}
});
});
it('click on a card should lead to the appropriate app', async () => {

View file

@ -21,7 +21,7 @@ export default function (context: FtrProviderContext) {
const config = context.getService('config');
describe('Interactive setup APIs - Enrollment flow', function () {
this.tags('skipCloud');
this.tags(['skipCloud', 'skipFIPS']);
let kibanaVerificationCode: string;
let elasticsearchCaFingerprint: string;

View file

@ -20,7 +20,7 @@ export default function (context: FtrProviderContext) {
const config = context.getService('config');
describe('Interactive setup APIs - Manual configuration flow', function () {
this.tags('skipCloud');
this.tags(['skipCloud', 'skipFIPS']);
let kibanaVerificationCode: string;
let elasticsearchCaCertificate: string;

View file

@ -19,7 +19,7 @@ export default function (context: FtrProviderContext) {
const config = context.getService('config');
describe('Interactive setup APIs - Manual configuration flow without TLS', function () {
this.tags('skipCloud');
this.tags(['skipCloud', 'skipFIPS']);
let kibanaVerificationCode: string;
before(async () => {

View file

@ -23,7 +23,7 @@ export default function ({ getService }: FtrProviderContext) {
const log = getService('log');
describe('Interactive Setup Functional Tests (Enrollment token)', function () {
this.tags('skipCloud');
this.tags(['skipCloud', 'skipFIPS']);
const elasticsearchConfig = config.get('servers.elasticsearch');
let verificationCode: string;

View file

@ -20,7 +20,7 @@ export default function ({ getService }: FtrProviderContext) {
const log = getService('log');
describe('Interactive Setup Functional Tests (Manual configuration)', function () {
this.tags('skipCloud');
this.tags(['skipCloud', 'skipFIPS']);
let verificationCode: string;
before(async function () {

View file

@ -20,7 +20,7 @@ export default function ({ getService, getPageObject }: FtrProviderContext) {
const log = getService('log');
describe('Interactive Setup Functional Tests (Manual configuration without Security)', function () {
this.tags('skipCloud');
this.tags(['skipCloud', 'skipFIPS']);
let verificationCode: string;
before(async function () {

View file

@ -20,7 +20,7 @@ export default function ({ getService }: FtrProviderContext) {
const log = getService('log');
describe('Interactive Setup Functional Tests (Manual configuration without TLS)', function () {
this.tags('skipCloud');
this.tags(['skipCloud', 'skipFIPS']);
let verificationCode: string;
before(async function () {

View file

@ -32,7 +32,8 @@ export default function ({ getService }: FtrProviderContext) {
.set('kbn-xsrf', 'xxx')
.expect(200);
describe('status service', () => {
describe('status service', function () {
this.tags('skipFIPS');
// This test must come first because the timeout only applies to the initial emission
it("returns a timeout for status check that doesn't emit after 30s", async () => {
let aStatus = await getStatus('statusPluginA');

View file

@ -13,6 +13,7 @@ export default function alertingApiIntegrationTests({
getService,
}: FtrProviderContext) {
describe('alerting api integration basic license', function () {
this.tags('skipFIPS');
loadTestFile(require.resolve('./actions'));
loadTestFile(require.resolve('./alerts'));
});

View file

@ -38,7 +38,8 @@ export function alertTests({ getService }: FtrProviderContext, space: Space) {
.then((response: SupertestResponse) => response.body);
}
describe('alerts', () => {
describe('alerts', function () {
this.tags('skipFIPS');
let alertUtils: AlertUtils;
let indexRecordActionId: string;
const authorizationIndex = '.kibana-test-authorization';

View file

@ -40,217 +40,223 @@ export default function createAlertTests({ getService }: FtrProviderContext) {
return scheduledTask._source!;
}
it('should handle create alert request appropriately', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
.expect(200);
const response = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
],
describe('create alert', function () {
this.tags('skipFIPS');
it('should handle create alert request appropriately', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
);
.expect(200);
expect(response.status).to.eql(200);
objectRemover.add(Spaces.space1.id, response.body.id, 'rule', 'alerting');
expect(response.body).to.eql({
id: response.body.id,
name: 'abc',
tags: ['foo'],
actions: [
{
id: createdAction.id,
connector_type_id: createdAction.connector_type_id,
group: 'default',
params: {},
uuid: response.body.actions[0].uuid,
},
],
enabled: true,
rule_type_id: 'test.noop',
revision: 0,
running: false,
consumer: 'alertsFixture',
params: {},
created_by: null,
schedule: { interval: '1m' },
scheduled_task_id: response.body.scheduled_task_id,
updated_by: null,
api_key_owner: null,
api_key_created_by_user: null,
throttle: '1m',
notify_when: 'onThrottleInterval',
mute_all: false,
muted_alert_ids: [],
created_at: response.body.created_at,
updated_at: response.body.updated_at,
execution_status: response.body.execution_status,
...(response.body.next_run ? { next_run: response.body.next_run } : {}),
...(response.body.last_run ? { last_run: response.body.last_run } : {}),
});
expect(Date.parse(response.body.created_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.eql(Date.parse(response.body.created_at));
if (response.body.next_run) {
expect(Date.parse(response.body.next_run)).to.be.greaterThan(0);
}
expect(typeof response.body.scheduled_task_id).to.be('string');
const taskRecord = await getScheduledTask(response.body.scheduled_task_id);
expect(taskRecord.type).to.eql('task');
expect(taskRecord.task.taskType).to.eql('alerting:test.noop');
expect(JSON.parse(taskRecord.task.params)).to.eql({
alertId: response.body.id,
spaceId: Spaces.space1.id,
consumer: 'alertsFixture',
});
expect(taskRecord.task.enabled).to.eql(true);
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: response.body.id,
const response = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
],
})
);
expect(response.status).to.eql(200);
objectRemover.add(Spaces.space1.id, response.body.id, 'rule', 'alerting');
expect(response.body).to.eql({
id: response.body.id,
name: 'abc',
tags: ['foo'],
actions: [
{
id: createdAction.id,
connector_type_id: createdAction.connector_type_id,
group: 'default',
params: {},
uuid: response.body.actions[0].uuid,
},
],
enabled: true,
rule_type_id: 'test.noop',
revision: 0,
running: false,
consumer: 'alertsFixture',
params: {},
created_by: null,
schedule: { interval: '1m' },
scheduled_task_id: response.body.scheduled_task_id,
updated_by: null,
api_key_owner: null,
api_key_created_by_user: null,
throttle: '1m',
notify_when: 'onThrottleInterval',
mute_all: false,
muted_alert_ids: [],
created_at: response.body.created_at,
updated_at: response.body.updated_at,
execution_status: response.body.execution_status,
...(response.body.next_run ? { next_run: response.body.next_run } : {}),
...(response.body.last_run ? { last_run: response.body.last_run } : {}),
});
expect(Date.parse(response.body.created_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.eql(Date.parse(response.body.created_at));
if (response.body.next_run) {
expect(Date.parse(response.body.next_run)).to.be.greaterThan(0);
}
expect(typeof response.body.scheduled_task_id).to.be('string');
const taskRecord = await getScheduledTask(response.body.scheduled_task_id);
expect(taskRecord.type).to.eql('task');
expect(taskRecord.task.taskType).to.eql('alerting:test.noop');
expect(JSON.parse(taskRecord.task.params)).to.eql({
alertId: response.body.id,
spaceId: Spaces.space1.id,
consumer: 'alertsFixture',
});
expect(taskRecord.task.enabled).to.eql(true);
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: response.body.id,
});
});
});
it('should store references correctly for actions', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
.expect(200);
const response = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
{
id: 'my-slack1',
group: 'default',
params: {
message: 'something important happened!',
},
},
],
describe('store references correctly', function () {
this.tags('skipFIPS');
it('should store references correctly for actions', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
);
.expect(200);
expect(response.status).to.eql(200);
const response = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
{
id: 'my-slack1',
group: 'default',
params: {
message: 'something important happened!',
},
},
],
})
);
objectRemover.add(Spaces.space1.id, response.body.id, 'rule', 'alerting');
expect(response.status).to.eql(200);
expect(response.body).to.eql({
id: response.body.id,
name: 'abc',
tags: ['foo'],
actions: [
objectRemover.add(Spaces.space1.id, response.body.id, 'rule', 'alerting');
expect(response.body).to.eql({
id: response.body.id,
name: 'abc',
tags: ['foo'],
actions: [
{
id: createdAction.id,
connector_type_id: createdAction.connector_type_id,
group: 'default',
params: {},
uuid: response.body.actions[0].uuid,
},
{
id: 'my-slack1',
group: 'default',
connector_type_id: '.slack',
params: {
message: 'something important happened!',
},
uuid: response.body.actions[1].uuid,
},
],
enabled: true,
rule_type_id: 'test.noop',
revision: 0,
running: false,
consumer: 'alertsFixture',
params: {},
created_by: null,
schedule: { interval: '1m' },
scheduled_task_id: response.body.scheduled_task_id,
updated_by: null,
api_key_owner: null,
api_key_created_by_user: null,
throttle: '1m',
notify_when: 'onThrottleInterval',
mute_all: false,
muted_alert_ids: [],
created_at: response.body.created_at,
updated_at: response.body.updated_at,
execution_status: response.body.execution_status,
...(response.body.next_run ? { next_run: response.body.next_run } : {}),
...(response.body.last_run ? { last_run: response.body.last_run } : {}),
});
if (response.body.next_run) {
expect(Date.parse(response.body.next_run)).to.be.greaterThan(0);
}
const esResponse = await es.get<SavedObject<RawRule>>(
{
id: createdAction.id,
connector_type_id: createdAction.connector_type_id,
index: ALERTING_CASES_SAVED_OBJECT_INDEX,
id: `alert:${response.body.id}`,
},
{ meta: true }
);
expect(esResponse.statusCode).to.eql(200);
const rawActions = (esResponse.body._source as any)?.alert.actions ?? [];
expect(rawActions).to.eql([
{
actionRef: 'action_0',
actionTypeId: 'test.noop',
group: 'default',
params: {},
uuid: response.body.actions[0].uuid,
uuid: rawActions[0].uuid,
},
{
id: 'my-slack1',
actionRef: 'preconfigured:my-slack1',
actionTypeId: '.slack',
group: 'default',
connector_type_id: '.slack',
params: {
message: 'something important happened!',
},
uuid: response.body.actions[1].uuid,
uuid: rawActions[1].uuid,
},
],
enabled: true,
rule_type_id: 'test.noop',
revision: 0,
running: false,
consumer: 'alertsFixture',
params: {},
created_by: null,
schedule: { interval: '1m' },
scheduled_task_id: response.body.scheduled_task_id,
updated_by: null,
api_key_owner: null,
api_key_created_by_user: null,
throttle: '1m',
notify_when: 'onThrottleInterval',
mute_all: false,
muted_alert_ids: [],
created_at: response.body.created_at,
updated_at: response.body.updated_at,
execution_status: response.body.execution_status,
...(response.body.next_run ? { next_run: response.body.next_run } : {}),
...(response.body.last_run ? { last_run: response.body.last_run } : {}),
});
]);
if (response.body.next_run) {
expect(Date.parse(response.body.next_run)).to.be.greaterThan(0);
}
const references = esResponse.body._source?.references ?? [];
const esResponse = await es.get<SavedObject<RawRule>>(
{
index: ALERTING_CASES_SAVED_OBJECT_INDEX,
id: `alert:${response.body.id}`,
},
{ meta: true }
);
expect(esResponse.statusCode).to.eql(200);
const rawActions = (esResponse.body._source as any)?.alert.actions ?? [];
expect(rawActions).to.eql([
{
actionRef: 'action_0',
actionTypeId: 'test.noop',
group: 'default',
params: {},
uuid: rawActions[0].uuid,
},
{
actionRef: 'preconfigured:my-slack1',
actionTypeId: '.slack',
group: 'default',
params: {
message: 'something important happened!',
},
uuid: rawActions[1].uuid,
},
]);
const references = esResponse.body._source?.references ?? [];
expect(references.length).to.eql(1);
expect(references[0]).to.eql({
id: createdAction.id,
name: 'action_0',
type: 'action',
expect(references.length).to.eql(1);
expect(references[0]).to.eql({
id: createdAction.id,
name: 'action_0',
type: 'action',
});
});
});
@ -631,7 +637,8 @@ export default function createAlertTests({ getService }: FtrProviderContext) {
});
});
describe('legacy', () => {
describe('legacy', function () {
this.tags('skipFIPS');
it('should handle create alert request appropriately', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)

View file

@ -31,7 +31,8 @@ export default function createDisableRuleTests({ getService }: FtrProviderContex
const retry = getService('retry');
const supertest = getService('supertest');
describe('disable', () => {
describe('disable', function () {
this.tags('skipFIPS');
const objectRemover = new ObjectRemover(supertestWithoutAuth);
const ruleUtils = new RuleUtils({ space: Spaces.space1, supertestWithoutAuth });
@ -265,7 +266,7 @@ export default function createDisableRuleTests({ getService }: FtrProviderContex
});
});
describe('legacy', () => {
describe('legacy', function () {
it('should handle disable rule request appropriately', async () => {
const { body: createdRule } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)

View file

@ -37,59 +37,66 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex
return scheduledTask._source!;
}
it('should handle enable alert request appropriately', async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData({ enabled: false }))
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
describe('handle enable alert request', function () {
this.tags('skipFIPS');
it('should handle enable alert request appropriately', async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData({ enabled: false }))
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
await alertUtils.enable(createdAlert.id);
await alertUtils.enable(createdAlert.id);
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(typeof updatedAlert.scheduled_task_id).to.eql('string');
const taskRecord = await getScheduledTask(updatedAlert.scheduled_task_id);
expect(taskRecord.type).to.eql('task');
expect(taskRecord.task.taskType).to.eql('alerting:test.noop');
expect(JSON.parse(taskRecord.task.params)).to.eql({
alertId: createdAlert.id,
spaceId: Spaces.space1.id,
consumer: 'alertsFixture',
});
expect(taskRecord.task.enabled).to.eql(true);
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(typeof updatedAlert.scheduled_task_id).to.eql('string');
const taskRecord = await getScheduledTask(updatedAlert.scheduled_task_id);
expect(taskRecord.type).to.eql('task');
expect(taskRecord.task.taskType).to.eql('alerting:test.noop');
expect(JSON.parse(taskRecord.task.params)).to.eql({
alertId: createdAlert.id,
spaceId: Spaces.space1.id,
consumer: 'alertsFixture',
});
expect(taskRecord.task.enabled).to.eql(true);
// Ensure revision was not updated
expect(updatedAlert.revision).to.eql(0);
// Ensure revision was not updated
expect(updatedAlert.revision).to.eql(0);
// Ensure AAD isn't broken
await checkAAD({
supertest: supertestWithoutAuth,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdAlert.id,
// Ensure AAD isn't broken
await checkAAD({
supertest: supertestWithoutAuth,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdAlert.id,
});
});
});
it(`shouldn't enable alert from another space`, async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.other.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData({ enabled: false }))
.expect(200);
objectRemover.add(Spaces.other.id, createdAlert.id, 'rule', 'alerting');
describe(`shouldn't enable alert from another space`, function () {
this.tags('skipFIPS');
it(`shouldn't enable alert from another space`, async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.other.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData({ enabled: false }))
.expect(200);
objectRemover.add(Spaces.other.id, createdAlert.id, 'rule', 'alerting');
await alertUtils.getEnableRequest(createdAlert.id).expect(404, {
statusCode: 404,
error: 'Not Found',
message: `Saved object [alert/${createdAlert.id}] not found`,
await alertUtils.getEnableRequest(createdAlert.id).expect(404, {
statusCode: 404,
error: 'Not Found',
message: `Saved object [alert/${createdAlert.id}] not found`,
});
});
});
describe('legacy', () => {
describe('legacy', function () {
this.tags('skipFIPS');
it('should handle enable alert request appropriately', async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)

View file

@ -33,105 +33,108 @@ const findTestUtils = (
) => {
describe(describeType, () => {
afterEach(() => objectRemover.removeAll());
it('should handle find alert request appropriately', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
.expect(200);
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
actions: [
{
group: 'default',
id: createdAction.id,
params: {},
frequency: {
summary: false,
notify_when: 'onThrottleInterval',
throttle: '1m',
},
},
],
notify_when: undefined,
throttle: undefined,
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/${
describeType === 'public' ? 'api' : 'internal'
}/alerting/rules/_find?search=test.noop&search_fields=alertTypeId`
);
expect(response.status).to.eql(200);
expect(response.body.page).to.equal(1);
expect(response.body.per_page).to.be.greaterThan(0);
expect(response.body.total).to.be.greaterThan(0);
const match = response.body.data.find((obj: any) => obj.id === createdAlert.id);
const activeSnoozes = match.active_snoozes;
const hasActiveSnoozes = !!(activeSnoozes || []).filter((obj: any) => obj).length;
expect(match).to.eql({
id: createdAlert.id,
name: 'abc',
tags: ['foo'],
rule_type_id: 'test.noop',
revision: 0,
running: false,
consumer: 'alertsFixture',
schedule: { interval: '1m' },
enabled: true,
actions: [
{
group: 'default',
id: createdAction.id,
describe('handle find alert request', function () {
this.tags('skipFIPS');
it('should handle find alert request appropriately', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
params: {},
frequency: {
summary: false,
notify_when: 'onThrottleInterval',
throttle: '1m',
config: {},
secrets: {},
})
.expect(200);
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
actions: [
{
group: 'default',
id: createdAction.id,
params: {},
frequency: {
summary: false,
notify_when: 'onThrottleInterval',
throttle: '1m',
},
},
],
notify_when: undefined,
throttle: undefined,
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/${
describeType === 'public' ? 'api' : 'internal'
}/alerting/rules/_find?search=test.noop&search_fields=alertTypeId`
);
expect(response.status).to.eql(200);
expect(response.body.page).to.equal(1);
expect(response.body.per_page).to.be.greaterThan(0);
expect(response.body.total).to.be.greaterThan(0);
const match = response.body.data.find((obj: any) => obj.id === createdAlert.id);
const activeSnoozes = match.active_snoozes;
const hasActiveSnoozes = !!(activeSnoozes || []).filter((obj: any) => obj).length;
expect(match).to.eql({
id: createdAlert.id,
name: 'abc',
tags: ['foo'],
rule_type_id: 'test.noop',
revision: 0,
running: false,
consumer: 'alertsFixture',
schedule: { interval: '1m' },
enabled: true,
actions: [
{
group: 'default',
id: createdAction.id,
connector_type_id: 'test.noop',
params: {},
frequency: {
summary: false,
notify_when: 'onThrottleInterval',
throttle: '1m',
},
uuid: match.actions[0].uuid,
},
uuid: match.actions[0].uuid,
},
],
params: {},
created_by: null,
api_key_owner: null,
api_key_created_by_user: null,
scheduled_task_id: match.scheduled_task_id,
updated_by: null,
throttle: null,
notify_when: null,
mute_all: false,
muted_alert_ids: [],
created_at: match.created_at,
updated_at: match.updated_at,
execution_status: match.execution_status,
...(match.next_run ? { next_run: match.next_run } : {}),
...(match.last_run ? { last_run: match.last_run } : {}),
...(describeType === 'internal'
? {
monitoring: match.monitoring,
snooze_schedule: match.snooze_schedule,
...(hasActiveSnoozes && { active_snoozes: activeSnoozes }),
is_snoozed_until: null,
}
: {}),
],
params: {},
created_by: null,
api_key_owner: null,
api_key_created_by_user: null,
scheduled_task_id: match.scheduled_task_id,
updated_by: null,
throttle: null,
notify_when: null,
mute_all: false,
muted_alert_ids: [],
created_at: match.created_at,
updated_at: match.updated_at,
execution_status: match.execution_status,
...(match.next_run ? { next_run: match.next_run } : {}),
...(match.last_run ? { last_run: match.last_run } : {}),
...(describeType === 'internal'
? {
monitoring: match.monitoring,
snooze_schedule: match.snooze_schedule,
...(hasActiveSnoozes && { active_snoozes: activeSnoozes }),
is_snoozed_until: null,
}
: {}),
});
expect(Date.parse(match.created_at)).to.be.greaterThan(0);
expect(Date.parse(match.updated_at)).to.be.greaterThan(0);
});
expect(Date.parse(match.created_at)).to.be.greaterThan(0);
expect(Date.parse(match.updated_at)).to.be.greaterThan(0);
});
it(`shouldn't find alert from another space`, async () => {
@ -331,7 +334,8 @@ export default function createFindTests({ getService }: FtrProviderContext) {
findTestUtils('public', supertest, objectRemover);
findTestUtils('internal', supertest, objectRemover);
describe('legacy', () => {
describe('legacy', function () {
this.tags('skipFIPS');
it('should handle find alert request appropriately', async () => {
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)

View file

@ -18,60 +18,63 @@ const getTestUtils = (
) => {
describe(describeType, () => {
afterEach(() => objectRemover.removeAll());
it('should handle get alert request appropriately', async () => {
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
describe('handle get alert request', function () {
this.tags('skipFIPS');
it('should handle get alert request appropriately', async () => {
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/${
describeType === 'public' ? 'api' : 'internal'
}/alerting/rule/${createdAlert.id}`
);
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/${
describeType === 'public' ? 'api' : 'internal'
}/alerting/rule/${createdAlert.id}`
);
expect(response.status).to.eql(200);
expect(response.body).to.eql({
id: createdAlert.id,
name: 'abc',
tags: ['foo'],
rule_type_id: 'test.noop',
revision: 0,
running: false,
consumer: 'alertsFixture',
schedule: { interval: '1m' },
enabled: true,
actions: [],
params: {},
created_by: null,
scheduled_task_id: response.body.scheduled_task_id,
updated_by: null,
api_key_owner: null,
api_key_created_by_user: null,
throttle: '1m',
notify_when: 'onThrottleInterval',
mute_all: false,
muted_alert_ids: [],
created_at: response.body.created_at,
updated_at: response.body.updated_at,
execution_status: response.body.execution_status,
...(response.body.next_run ? { next_run: response.body.next_run } : {}),
...(response.body.last_run ? { last_run: response.body.last_run } : {}),
...(describeType === 'internal'
? {
monitoring: response.body.monitoring,
snooze_schedule: response.body.snooze_schedule,
is_snoozed_until: response.body.is_snoozed_until,
}
: {}),
expect(response.status).to.eql(200);
expect(response.body).to.eql({
id: createdAlert.id,
name: 'abc',
tags: ['foo'],
rule_type_id: 'test.noop',
revision: 0,
running: false,
consumer: 'alertsFixture',
schedule: { interval: '1m' },
enabled: true,
actions: [],
params: {},
created_by: null,
scheduled_task_id: response.body.scheduled_task_id,
updated_by: null,
api_key_owner: null,
api_key_created_by_user: null,
throttle: '1m',
notify_when: 'onThrottleInterval',
mute_all: false,
muted_alert_ids: [],
created_at: response.body.created_at,
updated_at: response.body.updated_at,
execution_status: response.body.execution_status,
...(response.body.next_run ? { next_run: response.body.next_run } : {}),
...(response.body.last_run ? { last_run: response.body.last_run } : {}),
...(describeType === 'internal'
? {
monitoring: response.body.monitoring,
snooze_schedule: response.body.snooze_schedule,
is_snoozed_until: response.body.is_snoozed_until,
}
: {}),
});
expect(Date.parse(response.body.created_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0);
if (response.body.next_run) {
expect(Date.parse(response.body.next_run)).to.be.greaterThan(0);
}
});
expect(Date.parse(response.body.created_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0);
if (response.body.next_run) {
expect(Date.parse(response.body.next_run)).to.be.greaterThan(0);
}
});
it(`shouldn't find alert from another space`, async () => {
@ -122,7 +125,8 @@ export default function createGetTests({ getService }: FtrProviderContext) {
getTestUtils('public', objectRemover, supertest);
getTestUtils('internal', objectRemover, supertest);
describe('legacy', () => {
describe('legacy', function () {
this.tags('skipFIPS');
it('should handle get alert request appropriately', async () => {
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)

View file

@ -163,28 +163,33 @@ export default function createGetAlertSummaryTests({ getService }: FtrProviderCo
});
});
it('handles muted alerts', async () => {
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
describe('muted alerts', function () {
this.tags('skipFIPS');
it('handles muted alerts', async () => {
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
await alertUtils.muteInstance(createdRule.id, '1');
await waitForEvents(createdRule.id, ['execute']);
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}/_alert_summary`
);
await alertUtils.muteInstance(createdRule.id, '1');
await waitForEvents(createdRule.id, ['execute']);
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${
createdRule.id
}/_alert_summary`
);
expect(response.status).to.eql(200);
expect(response.body.alerts).to.eql({
'1': {
status: 'OK',
muted: true,
flapping: false,
tracked: true,
},
expect(response.status).to.eql(200);
expect(response.body.alerts).to.eql({
'1': {
status: 'OK',
muted: true,
flapping: false,
tracked: true,
},
});
});
});
@ -208,165 +213,176 @@ export default function createGetAlertSummaryTests({ getService }: FtrProviderCo
expect(errorMessage.message).to.be('this alert is intended to fail');
});
it('handles multi-alert status', async () => {
// pattern of when the rule should fire
const pattern = {
alertA: [true, true, true, true],
alertB: [true, true, false, false],
alertC: [true, true, true, true],
};
describe('multi-alert', function () {
this.tags('skipFIPS');
it('handles multi-alert status', async () => {
// pattern of when the rule should fire
const pattern = {
alertA: [true, true, true, true],
alertB: [true, true, false, false],
alertC: [true, true, true, true],
};
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
rule_type_id: 'test.patternFiring',
params: { pattern },
schedule: { interval: '1s' },
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
rule_type_id: 'test.patternFiring',
params: { pattern },
schedule: { interval: '1s' },
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
await alertUtils.muteInstance(createdRule.id, 'alertC');
await alertUtils.muteInstance(createdRule.id, 'alertD');
await waitForEvents(createdRule.id, ['new-instance', 'recovered-instance']);
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}/_alert_summary`
);
await alertUtils.muteInstance(createdRule.id, 'alertC');
await alertUtils.muteInstance(createdRule.id, 'alertD');
await waitForEvents(createdRule.id, ['new-instance', 'recovered-instance']);
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${
createdRule.id
}/_alert_summary`
);
const actualAlerts = checkAndCleanActualAlerts(response.body.alerts, [
'alertA',
'alertB',
'alertC',
]);
const actualAlerts = checkAndCleanActualAlerts(response.body.alerts, [
'alertA',
'alertB',
'alertC',
]);
const expectedAlerts = {
alertA: {
status: 'Active',
muted: false,
actionGroupId: 'default',
activeStartDate: actualAlerts.alertA.activeStartDate,
flapping: false,
tracked: true,
},
alertB: {
status: 'OK',
muted: false,
flapping: false,
tracked: true,
},
alertC: {
status: 'Active',
muted: true,
actionGroupId: 'default',
activeStartDate: actualAlerts.alertC.activeStartDate,
flapping: false,
tracked: true,
},
alertD: {
status: 'OK',
muted: true,
flapping: false,
tracked: true,
},
};
expect(actualAlerts).to.eql(expectedAlerts);
});
it('handles multi-alert status during maintenance window', async () => {
const { body: createdMaintenanceWindow } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/maintenance_window`)
.set('kbn-xsrf', 'foo')
.send({
title: 'test-maintenance-window',
duration: 60 * 60 * 1000, // 1 hr
r_rule: {
dtstart: new Date().toISOString(),
tzid: 'UTC',
freq: 2, // weekly
const expectedAlerts = {
alertA: {
status: 'Active',
muted: false,
actionGroupId: 'default',
activeStartDate: actualAlerts.alertA.activeStartDate,
flapping: false,
tracked: true,
},
});
objectRemover.add(
Spaces.space1.id,
createdMaintenanceWindow.id,
'rules/maintenance_window',
'alerting',
true
);
// pattern of when the rule should fire
const pattern = {
alertA: [true, true, true, true],
alertB: [true, true, false, false],
alertC: [true, true, true, true],
};
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
rule_type_id: 'test.patternFiring',
params: { pattern },
schedule: { interval: '1s' },
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
await alertUtils.muteInstance(createdRule.id, 'alertC');
await alertUtils.muteInstance(createdRule.id, 'alertD');
await waitForEvents(createdRule.id, ['new-instance', 'recovered-instance']);
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}/_alert_summary`
);
const actualAlerts = checkAndCleanActualAlerts(response.body.alerts, [
'alertA',
'alertB',
'alertC',
]);
const expectedAlerts = {
alertA: {
status: 'Active',
muted: false,
actionGroupId: 'default',
activeStartDate: actualAlerts.alertA.activeStartDate,
flapping: false,
tracked: true,
maintenanceWindowIds: [createdMaintenanceWindow.id],
},
alertB: {
status: 'OK',
muted: false,
flapping: false,
tracked: true,
maintenanceWindowIds: [createdMaintenanceWindow.id],
},
alertC: {
status: 'Active',
muted: true,
actionGroupId: 'default',
activeStartDate: actualAlerts.alertC.activeStartDate,
flapping: false,
tracked: true,
maintenanceWindowIds: [createdMaintenanceWindow.id],
},
alertD: {
status: 'OK',
muted: true,
flapping: false,
tracked: true,
},
};
expect(actualAlerts).to.eql(expectedAlerts);
alertB: {
status: 'OK',
muted: false,
flapping: false,
tracked: true,
},
alertC: {
status: 'Active',
muted: true,
actionGroupId: 'default',
activeStartDate: actualAlerts.alertC.activeStartDate,
flapping: false,
tracked: true,
},
alertD: {
status: 'OK',
muted: true,
flapping: false,
tracked: true,
},
};
expect(actualAlerts).to.eql(expectedAlerts);
});
});
describe('legacy', () => {
describe('multi-alert maintenance window', function () {
this.tags('skipFIPS');
it('handles multi-alert status during maintenance window', async () => {
const { body: createdMaintenanceWindow } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/maintenance_window`)
.set('kbn-xsrf', 'foo')
.send({
title: 'test-maintenance-window',
duration: 60 * 60 * 1000, // 1 hr
r_rule: {
dtstart: new Date().toISOString(),
tzid: 'UTC',
freq: 2, // weekly
},
});
objectRemover.add(
Spaces.space1.id,
createdMaintenanceWindow.id,
'rules/maintenance_window',
'alerting',
true
);
// pattern of when the rule should fire
const pattern = {
alertA: [true, true, true, true],
alertB: [true, true, false, false],
alertC: [true, true, true, true],
};
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
rule_type_id: 'test.patternFiring',
params: { pattern },
schedule: { interval: '1s' },
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
await alertUtils.muteInstance(createdRule.id, 'alertC');
await alertUtils.muteInstance(createdRule.id, 'alertD');
await waitForEvents(createdRule.id, ['new-instance', 'recovered-instance']);
const response = await supertest.get(
`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${
createdRule.id
}/_alert_summary`
);
const actualAlerts = checkAndCleanActualAlerts(response.body.alerts, [
'alertA',
'alertB',
'alertC',
]);
const expectedAlerts = {
alertA: {
status: 'Active',
muted: false,
actionGroupId: 'default',
activeStartDate: actualAlerts.alertA.activeStartDate,
flapping: false,
tracked: true,
maintenanceWindowIds: [createdMaintenanceWindow.id],
},
alertB: {
status: 'OK',
muted: false,
flapping: false,
tracked: true,
maintenanceWindowIds: [createdMaintenanceWindow.id],
},
alertC: {
status: 'Active',
muted: true,
actionGroupId: 'default',
activeStartDate: actualAlerts.alertC.activeStartDate,
flapping: false,
tracked: true,
maintenanceWindowIds: [createdMaintenanceWindow.id],
},
alertD: {
status: 'OK',
muted: true,
flapping: false,
tracked: true,
},
};
expect(actualAlerts).to.eql(expectedAlerts);
});
});
describe('legacy', function () {
this.tags('skipFIPS');
it('handles multi-alert status', async () => {
// pattern of when the alert should fire
const pattern = {

View file

@ -31,105 +31,114 @@ export default function createAggregateTests({ getService }: FtrProviderContext)
afterEach(() => objectRemover.removeAll());
it('should get rule tags when there are no rules', async () => {
const response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags`)
.expect(200);
describe('get rule tags when there are no rules', function () {
this.tags('skipFIPS');
it('should get rule tags when there are no rules', async () => {
const response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags`)
.expect(200);
expect(response.body).to.eql({
data: [],
per_page: 50,
page: 1,
total: 0,
expect(response.body).to.eql({
data: [],
per_page: 50,
page: 1,
total: 0,
});
});
});
it('should get rule tags from all rules', async () => {
await Promise.all(
tags.map(async (tag, index) => {
await createRule({ tags: [tag, `${tag}_${index}`] });
})
);
describe('get rule tags from all rules', function () {
this.tags('skipFIPS');
it('should get rule tags from all rules', async () => {
await Promise.all(
tags.map(async (tag, index) => {
await createRule({ tags: [tag, `${tag}_${index}`] });
})
);
await createRule({ tags: ['a', 'b', 'c', '1', '2'] });
await createRule({ tags: ['a', 'b', 'c', '1', '2'] });
const response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags`)
.expect(200);
const response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags`)
.expect(200);
expect(response.body).to.eql({
data: [
'1',
'2',
'a',
'a_0',
'b',
'b_1',
'c',
'c_2',
'd',
'd_3',
'e',
'e_4',
'f',
'f_5',
'g',
'g_6',
'h',
'h_7',
'i',
'i_8',
'j',
'j_9',
],
per_page: 50,
page: 1,
total: 22,
expect(response.body).to.eql({
data: [
'1',
'2',
'a',
'a_0',
'b',
'b_1',
'c',
'c_2',
'd',
'd_3',
'e',
'e_4',
'f',
'f_5',
'g',
'g_6',
'h',
'h_7',
'i',
'i_8',
'j',
'j_9',
],
per_page: 50,
page: 1,
total: 22,
});
});
});
it('should paginate rule tags', async () => {
await createRule({
tags: ['1', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '110'],
});
await createRule({
tags: ['2', '20', '21', '22', '23', '24', '25', '26', '1', '111', '1111'],
});
await createRule({
tags: ['3', '30', '31', '32', '33', '34', '35', '36', '37', '1', '111', '11_11'],
});
describe('paginate rule tags', function () {
this.tags('skipFIPS');
it('should paginate rule tags', async () => {
await createRule({
tags: ['1', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '110'],
});
await createRule({
tags: ['2', '20', '21', '22', '23', '24', '25', '26', '1', '111', '1111'],
});
await createRule({
tags: ['3', '30', '31', '32', '33', '34', '35', '36', '37', '1', '111', '11_11'],
});
let response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags?page=1&per_page=10`)
.expect(200);
let response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags?page=1&per_page=10`)
.expect(200);
expect(response.body).to.eql({
data: ['1', '10', '11', '110', '111', '1111', '11_11', '12', '13', '14'],
per_page: 10,
page: 1,
total: 32,
});
expect(response.body).to.eql({
data: ['1', '10', '11', '110', '111', '1111', '11_11', '12', '13', '14'],
per_page: 10,
page: 1,
total: 32,
});
response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags?page=2&per_page=10`)
.expect(200);
response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags?page=2&per_page=10`)
.expect(200);
expect(response.body).to.eql({
data: ['15', '16', '17', '18', '19', '2', '20', '21', '22', '23'],
per_page: 10,
page: 2,
total: 32,
});
expect(response.body).to.eql({
data: ['15', '16', '17', '18', '19', '2', '20', '21', '22', '23'],
per_page: 10,
page: 2,
total: 32,
});
response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags?page=4&per_page=10`)
.expect(200);
response = await supertest
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_tags?page=4&per_page=10`)
.expect(200);
expect(response.body).to.eql({
data: ['36', '37'],
per_page: 10,
page: 4,
total: 32,
expect(response.body).to.eql({
data: ['36', '37'],
per_page: 10,
page: 4,
total: 32,
});
});
});

View file

@ -184,42 +184,46 @@ export default function executionStatusAlertTests({ getService }: FtrProviderCon
await ensureAlertUpdatedAtHasNotChanged(alertId, alertUpdatedAt);
});
it('should eventually have error reason "validate" when appropriate', async () => {
const response = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
rule_type_id: 'test.validation',
schedule: { interval: '1s' },
params: { param1: 'valid now, but will change to a number soon!' },
describe('eventually have error reason "validate" when appropriate', function () {
this.tags('skipFIPS');
it('should eventually have error reason "validate" when appropriate', async () => {
const response = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
rule_type_id: 'test.validation',
schedule: { interval: '1s' },
params: { param1: 'valid now, but will change to a number soon!' },
})
);
expect(response.status).to.eql(200);
const alertId = response.body.id;
const alertUpdatedAt = response.body.updated_at;
objectRemover.add(Spaces.space1.id, alertId, 'rule', 'alerting');
let executionStatus = await waitForStatus(alertId, new Set(['ok']));
// break the validation of the params
await supertest
.put(`${getUrlPrefix(Spaces.space1.id)}/api/alerts_fixture/saved_object/alert/${alertId}`)
.set('kbn-xsrf', 'foo')
.send({
attributes: {
params: { param1: 42 },
},
})
);
expect(response.status).to.eql(200);
const alertId = response.body.id;
const alertUpdatedAt = response.body.updated_at;
objectRemover.add(Spaces.space1.id, alertId, 'rule', 'alerting');
.expect(200);
let executionStatus = await waitForStatus(alertId, new Set(['ok']));
executionStatus = await waitForStatus(alertId, new Set(['error']));
expect(executionStatus.error).to.be.ok();
expect(executionStatus.error.reason).to.be('validate');
await ensureAlertUpdatedAtHasNotChanged(alertId, alertUpdatedAt);
// break the validation of the params
await supertest
.put(`${getUrlPrefix(Spaces.space1.id)}/api/alerts_fixture/saved_object/alert/${alertId}`)
.set('kbn-xsrf', 'foo')
.send({
attributes: {
params: { param1: 42 },
},
})
.expect(200);
executionStatus = await waitForStatus(alertId, new Set(['error']));
expect(executionStatus.error).to.be.ok();
expect(executionStatus.error.reason).to.be('validate');
await ensureAlertUpdatedAtHasNotChanged(alertId, alertUpdatedAt);
const message = 'params invalid: [param1]: expected value of type [string] but got [number]';
expect(executionStatus.error.message).to.be(message);
const message =
'params invalid: [param1]: expected value of type [string] but got [number]';
expect(executionStatus.error.message).to.be(message);
});
});
it('should be able to find over all the fields', async () => {

View file

@ -21,7 +21,8 @@ import {
export default function createMuteTests({ getService }: FtrProviderContext) {
const supertestWithoutAuth = getService('supertestWithoutAuth');
describe('mute_all', () => {
describe('mute_all', function () {
this.tags('skipFIPS');
const objectRemover = new ObjectRemover(supertestWithoutAuth);
const alertUtils = new AlertUtils({ space: Spaces.space1, supertestWithoutAuth });

View file

@ -21,7 +21,8 @@ import {
export default function createMuteInstanceTests({ getService }: FtrProviderContext) {
const supertestWithoutAuth = getService('supertestWithoutAuth');
describe('mute_instance', () => {
describe('mute_instance', function () {
this.tags('skipFIPS');
const objectRemover = new ObjectRemover(supertestWithoutAuth);
const alertUtils = new AlertUtils({ space: Spaces.space1, supertestWithoutAuth });

View file

@ -21,7 +21,8 @@ import {
export default function createUnmuteTests({ getService }: FtrProviderContext) {
const supertestWithoutAuth = getService('supertestWithoutAuth');
describe('unmute_all', () => {
describe('unmute_all', function () {
this.tags('skipFIPS');
const objectRemover = new ObjectRemover(supertestWithoutAuth);
const alertUtils = new AlertUtils({ space: Spaces.space1, supertestWithoutAuth });

View file

@ -21,7 +21,8 @@ import {
export default function createUnmuteInstanceTests({ getService }: FtrProviderContext) {
const supertestWithoutAuth = getService('supertestWithoutAuth');
describe('unmute_instance', () => {
describe('unmute_instance', function () {
this.tags('skipFIPS');
const objectRemover = new ObjectRemover(supertestWithoutAuth);
const alertUtils = new AlertUtils({ space: Spaces.space1, supertestWithoutAuth });

View file

@ -20,86 +20,89 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
after(() => objectRemover.removeAll());
it('should handle update alert request appropriately', async () => {
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
describe('handle update alert request appropriately', function () {
this.tags('skipFIPS');
it('should handle update alert request appropriately', async () => {
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
const updatedData = {
name: 'bcd',
tags: ['bar'],
params: {
foo: true,
risk_score: 40,
severity: 'medium',
},
schedule: { interval: '12s' },
actions: [],
throttle: '1m',
notify_when: 'onThrottleInterval',
};
let response = await supertest
.put(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`)
.set('kbn-xsrf', 'foo')
.send(updatedData)
.expect(200);
const updatedData = {
name: 'bcd',
tags: ['bar'],
params: {
foo: true,
risk_score: 40,
severity: 'medium',
},
schedule: { interval: '12s' },
actions: [],
throttle: '1m',
notify_when: 'onThrottleInterval',
};
let response = await supertest
.put(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`)
.set('kbn-xsrf', 'foo')
.send(updatedData)
.expect(200);
expect(response.body).to.eql({
...updatedData,
id: createdAlert.id,
tags: ['bar'],
rule_type_id: 'test.noop',
running: false,
consumer: 'alertsFixture',
created_by: null,
enabled: true,
updated_by: null,
api_key_owner: null,
api_key_created_by_user: null,
mute_all: false,
muted_alert_ids: [],
notify_when: 'onThrottleInterval',
revision: 1,
scheduled_task_id: createdAlert.scheduled_task_id,
created_at: response.body.created_at,
updated_at: response.body.updated_at,
execution_status: response.body.execution_status,
mapped_params: {
expect(response.body).to.eql({
...updatedData,
id: createdAlert.id,
tags: ['bar'],
rule_type_id: 'test.noop',
running: false,
consumer: 'alertsFixture',
created_by: null,
enabled: true,
updated_by: null,
api_key_owner: null,
api_key_created_by_user: null,
mute_all: false,
muted_alert_ids: [],
notify_when: 'onThrottleInterval',
revision: 1,
scheduled_task_id: createdAlert.scheduled_task_id,
created_at: response.body.created_at,
updated_at: response.body.updated_at,
execution_status: response.body.execution_status,
mapped_params: {
risk_score: 40,
severity: '40-medium',
},
...(response.body.next_run ? { next_run: response.body.next_run } : {}),
...(response.body.last_run ? { last_run: response.body.last_run } : {}),
});
expect(Date.parse(response.body.created_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.be.greaterThan(
Date.parse(response.body.created_at)
);
if (response.body.next_run) {
expect(Date.parse(response.body.next_run)).to.be.greaterThan(0);
}
response = await supertest.get(
`${getUrlPrefix(
Spaces.space1.id
)}/internal/alerting/rules/_find?filter=alert.attributes.params.risk_score:40`
);
expect(response.body.data[0].mapped_params).to.eql({
risk_score: 40,
severity: '40-medium',
},
...(response.body.next_run ? { next_run: response.body.next_run } : {}),
...(response.body.last_run ? { last_run: response.body.last_run } : {}),
});
expect(Date.parse(response.body.created_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.be.greaterThan(0);
expect(Date.parse(response.body.updated_at)).to.be.greaterThan(
Date.parse(response.body.created_at)
);
if (response.body.next_run) {
expect(Date.parse(response.body.next_run)).to.be.greaterThan(0);
}
});
response = await supertest.get(
`${getUrlPrefix(
Spaces.space1.id
)}/internal/alerting/rules/_find?filter=alert.attributes.params.risk_score:40`
);
expect(response.body.data[0].mapped_params).to.eql({
risk_score: 40,
severity: '40-medium',
});
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdAlert.id,
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdAlert.id,
});
});
});
@ -174,7 +177,8 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
});
});
describe('legacy', () => {
describe('legacy', function () {
this.tags('skipFIPS');
it('should handle update alert request appropriately', async () => {
const { body: createdAlert } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)

View file

@ -31,50 +31,57 @@ export default function createUpdateApiKeyTests({ getService }: FtrProviderConte
after(() => objectRemover.removeAll());
it('should handle update alert api key appropriately', async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
describe('handle update alert api key appropriately', function () {
this.tags('skipFIPS');
it('should handle update alert api key appropriately', async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
await alertUtils.updateApiKey(createdAlert.id);
await alertUtils.updateApiKey(createdAlert.id);
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(updatedAlert.api_key_owner).to.eql(null);
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(updatedAlert.api_key_owner).to.eql(null);
// Ensure revision is not incremented when API key is updated
expect(updatedAlert.revision).to.eql(0);
// Ensure revision is not incremented when API key is updated
expect(updatedAlert.revision).to.eql(0);
// Ensure AAD isn't broken
await checkAAD({
supertest: supertestWithoutAuth,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdAlert.id,
// Ensure AAD isn't broken
await checkAAD({
supertest: supertestWithoutAuth,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdAlert.id,
});
});
});
it(`shouldn't update alert api key from another space`, async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.other.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.other.id, createdAlert.id, 'rule', 'alerting');
describe("shouldn't update alert api key", function () {
this.tags('skipFIPS');
it(`shouldn't update alert api key from another space`, async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.other.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData())
.expect(200);
objectRemover.add(Spaces.other.id, createdAlert.id, 'rule', 'alerting');
await alertUtils.getUpdateApiKeyRequest(createdAlert.id).expect(404, {
statusCode: 404,
error: 'Not Found',
message: `Saved object [alert/${createdAlert.id}] not found`,
await alertUtils.getUpdateApiKeyRequest(createdAlert.id).expect(404, {
statusCode: 404,
error: 'Not Found',
message: `Saved object [alert/${createdAlert.id}] not found`,
});
});
});
describe('legacy', () => {
describe('legacy', function () {
this.tags('skipFIPS');
it('should handle update alert api key appropriately', async () => {
const { body: createdAlert } = await supertestWithoutAuth
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)

View file

@ -10,7 +10,8 @@ import { buildUp, tearDown } from '../../helpers';
// eslint-disable-next-line import/no-default-export
export default function alertingTests({ loadTestFile, getService }: FtrProviderContext) {
describe('Alerting', () => {
describe('Alerting', function () {
this.tags('skipFIPS');
before(async () => await buildUp(getService));
after(async () => await tearDown(getService));

View file

@ -22,7 +22,8 @@ export default function createAlertDelayTests({ getService }: FtrProviderContext
const ACTIVE_PATH = 'alertInstances.instance.meta.activeCount';
const RECOVERED_PATH = 'alertRecoveredInstances.instance.meta.activeCount';
describe('Alert Delay', () => {
describe('Alert Delay', function () {
this.tags('skipFIPS');
let actionId: string;
const objectRemover = new ObjectRemover(supertestWithoutAuth);

View file

@ -60,7 +60,8 @@ export default function createAlertsAsDataInstallResourcesTest({ getService }: F
const alertsAsDataIndex = '.alerts-test.patternfiring.alerts-default';
const timestampPattern = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
describe('alerts as data', () => {
describe('alerts as data', function () {
this.tags('skipFIPS');
afterEach(async () => {
await objectRemover.removeAll();
await es.deleteByQuery({

View file

@ -70,7 +70,8 @@ export default function createAlertsAsDataAlertDelayInstallResourcesTest({
'.internal.alerts-observability.test.alerts.alerts-default-000001';
const timestampPattern = /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z/;
describe('alerts as data', () => {
describe('alerts as data', function () {
this.tags('skipFIPS');
before(async () => {
await esTestIndexTool.destroy();
await esTestIndexTool.setup();

View file

@ -55,7 +55,8 @@ export default function createAlertsAsDataInstallResourcesTest({ getService }: F
const ruleType = 'test.waitingRule';
const aadIndex = `.alerts-${ruleType.toLowerCase()}.alerts-default`;
describe(`should be handled for alerting framework based AaD`, () => {
describe(`should be handled for alerting framework based AaD`, function () {
this.tags('skipFIPS');
it('for a single conflicted alert', async () => {
const source = uuidv4();
const count = 1;

View file

@ -32,7 +32,8 @@ export default function createAlertsAsDataFlappingTest({ getService }: FtrProvid
const alertsAsDataIndex = '.alerts-test.patternfiring.alerts-default';
describe('alerts as data flapping', () => {
describe('alerts as data flapping', function () {
this.tags('skipFIPS');
beforeEach(async () => {
await es.deleteByQuery({
index: alertsAsDataIndex,

View file

@ -423,37 +423,40 @@ export default function createUpdateTests({ getService }: FtrProviderContext) {
});
});
it('should not bulk update API key with apiKey operation', async () => {
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
enabled: false,
})
);
describe('bulk update API key with apiKey operation', function () {
this.tags('skipFIPS');
it('should not bulk update API key with apiKey operation', async () => {
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
enabled: false,
})
);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
const payload = {
ids: [createdRule.id],
operations: [
{
operation: 'set',
field: 'apiKey',
},
],
};
const payload = {
ids: [createdRule.id],
operations: [
{
operation: 'set',
field: 'apiKey',
},
],
};
const bulkApiKeyResponse = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_bulk_edit`)
.set('kbn-xsrf', 'foo')
.send(payload);
const bulkApiKeyResponse = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rules/_bulk_edit`)
.set('kbn-xsrf', 'foo')
.send(payload);
expect(bulkApiKeyResponse.body.errors).to.have.length(0);
expect(bulkApiKeyResponse.body.rules).to.have.length(1);
expect(bulkApiKeyResponse.body.rules[0].api_key_owner).to.eql(null);
expect(bulkApiKeyResponse.body.rules[0].revision).to.eql(0);
expect(bulkApiKeyResponse.body.errors).to.have.length(0);
expect(bulkApiKeyResponse.body.rules).to.have.length(1);
expect(bulkApiKeyResponse.body.rules[0].api_key_owner).to.eql(null);
expect(bulkApiKeyResponse.body.rules[0].revision).to.eql(0);
});
});
it(`shouldn't bulk edit rule from another space`, async () => {

View file

@ -22,7 +22,8 @@ export default function createFlappingHistoryTests({ getService }: FtrProviderCo
const ACTIVE_PATH = 'alertInstances.instance.meta.flappingHistory';
const RECOVERED_PATH = 'alertRecoveredInstances.instance.meta.flappingHistory';
describe('Flapping History', () => {
describe('Flapping History', function () {
this.tags('skipFIPS');
let actionId: string;
const objectRemover = new ObjectRemover(supertestWithoutAuth);

View file

@ -32,7 +32,8 @@ export default function checkAlertSchemasTest({ getService }: FtrProviderContext
//
// and commit the changed schema files in packages/kbn-alerts-as-data-utils/src/schemas/generated/
describe('check alert schemas', () => {
describe('check alert schemas', function () {
this.tags('skipFIPS');
it('should not have discrepancies from the alert field map or the field map specific to a rule type', async () => {
// Generate base alert schema
createSchemaFromFieldMap({

View file

@ -62,96 +62,105 @@ export default function createScheduledTaskIdTests({ getService }: FtrProviderCo
.expect(409);
});
it('for migrated rules - sets scheduled task id to match rule id when rule is disabled then enabled', async () => {
const response = await supertest.get(
`${getUrlPrefix(``)}/api/alerting/rule/${MIGRATED_RULE_ID}`
);
expect(response.status).to.eql(200);
expect(response.body.scheduled_task_id).to.eql(MIGRATED_TASK_ID);
// scheduled task id should exist
const taskRecordLoaded = await getScheduledTask(MIGRATED_TASK_ID);
expect(JSON.parse(taskRecordLoaded.task.params)).to.eql({
alertId: MIGRATED_RULE_ID,
spaceId: 'default',
});
await supertestWithoutAuth
.post(`${getUrlPrefix(``)}/api/alerting/rule/${MIGRATED_RULE_ID}/_disable`)
.set('kbn-xsrf', 'foo')
.expect(204);
await supertestWithoutAuth
.post(`${getUrlPrefix(``)}/api/alerting/rule/${MIGRATED_RULE_ID}/_enable`)
.set('kbn-xsrf', 'foo')
.expect(204);
try {
await getScheduledTask(MIGRATED_TASK_ID);
throw new Error('Should have removed scheduled task');
} catch (e) {
expect(e.meta.statusCode).to.eql(404);
}
// scheduled task id that is same as rule id should exist
const taskRecordNew = await getScheduledTask(MIGRATED_RULE_ID);
expect(JSON.parse(taskRecordNew.task.params)).to.eql({
alertId: MIGRATED_RULE_ID,
spaceId: 'default',
consumer: 'alerts',
});
});
it('sets scheduled task id to rule id when rule is created', async () => {
const response = await supertestWithoutAuth
.post(`${getUrlPrefix(``)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData());
expect(response.status).to.eql(200);
objectRemover.add('default', response.body.id, 'rule', 'alerting');
expect(response.body.scheduled_task_id).to.eql(response.body.id);
const taskRecord = await getScheduledTask(response.body.scheduled_task_id);
expect(taskRecord.type).to.eql('task');
expect(taskRecord.task.taskType).to.eql('alerting:test.noop');
expect(JSON.parse(taskRecord.task.params)).to.eql({
alertId: response.body.id,
spaceId: 'default',
consumer: 'alertsFixture',
});
expect(taskRecord.task.enabled).to.eql(true);
});
it('deletes associated task for rule if task is unrecognized', async () => {
const RULE_ID = '46be60d4-ae63-48ed-ab6f-f4d9b4defacf';
// We've archived a disabled rule with a scheduled task ID that references
// a task with a removed task type. Task manager will mark the task as unrecognized.
// When we enable the rule, the unrecognized task should be removed and a new
// task created in its place
// scheduled task should exist and be unrecognized
await retry.try(async () => {
const taskRecordLoaded = await getScheduledTask(RULE_ID);
expect(taskRecordLoaded.task.status).to.equal('unrecognized');
});
// enable the rule
await supertestWithoutAuth
.post(`${getUrlPrefix(``)}/api/alerting/rule/${RULE_ID}/_enable`)
.set('kbn-xsrf', 'foo');
await retry.try(async () => {
const response = await supertestWithoutAuth.get(
`${getUrlPrefix(``)}/api/alerting/rule/${RULE_ID}`
describe('sets scheduled task id to match rule id when rule is disabled then enabled', function () {
this.tags('skipFIPS');
it('for migrated rules - sets scheduled task id to match rule id when rule is disabled then enabled', async () => {
const response = await supertest.get(
`${getUrlPrefix(``)}/api/alerting/rule/${MIGRATED_RULE_ID}`
);
expect(response.status).to.eql(200);
expect(response.body.scheduled_task_id).to.eql(MIGRATED_TASK_ID);
// scheduled task id should exist
const taskRecordLoaded = await getScheduledTask(MIGRATED_TASK_ID);
expect(JSON.parse(taskRecordLoaded.task.params)).to.eql({
alertId: MIGRATED_RULE_ID,
spaceId: 'default',
});
await supertestWithoutAuth
.post(`${getUrlPrefix(``)}/api/alerting/rule/${MIGRATED_RULE_ID}/_disable`)
.set('kbn-xsrf', 'foo')
.expect(204);
await supertestWithoutAuth
.post(`${getUrlPrefix(``)}/api/alerting/rule/${MIGRATED_RULE_ID}/_enable`)
.set('kbn-xsrf', 'foo')
.expect(204);
try {
await getScheduledTask(MIGRATED_TASK_ID);
throw new Error('Should have removed scheduled task');
} catch (e) {
expect(e.meta.statusCode).to.eql(404);
}
// scheduled task id that is same as rule id should exist
const taskRecordNew = await getScheduledTask(MIGRATED_RULE_ID);
expect(JSON.parse(taskRecordNew.task.params)).to.eql({
alertId: MIGRATED_RULE_ID,
spaceId: 'default',
consumer: 'alerts',
});
});
});
describe('sets scheduled task id to rule id', function () {
this.tags('skipFIPS');
it('sets scheduled task id to rule id when rule is created', async () => {
const response = await supertestWithoutAuth
.post(`${getUrlPrefix(``)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(getTestRuleData());
expect(response.status).to.eql(200);
expect(response.body.enabled).to.be(true);
});
objectRemover.add('default', response.body.id, 'rule', 'alerting');
// new scheduled task should exist with ID and status should not be unrecognized
const newTaskRecordLoaded = await getScheduledTask(RULE_ID);
expect(newTaskRecordLoaded.task.status).not.to.equal('unrecognized');
expect(response.body.scheduled_task_id).to.eql(response.body.id);
const taskRecord = await getScheduledTask(response.body.scheduled_task_id);
expect(taskRecord.type).to.eql('task');
expect(taskRecord.task.taskType).to.eql('alerting:test.noop');
expect(JSON.parse(taskRecord.task.params)).to.eql({
alertId: response.body.id,
spaceId: 'default',
consumer: 'alertsFixture',
});
expect(taskRecord.task.enabled).to.eql(true);
});
});
describe('deletes associated task for rule', function () {
this.tags('skipFIPS');
it('deletes associated task for rule if task is unrecognized', async () => {
const RULE_ID = '46be60d4-ae63-48ed-ab6f-f4d9b4defacf';
// We've archived a disabled rule with a scheduled task ID that references
// a task with a removed task type. Task manager will mark the task as unrecognized.
// When we enable the rule, the unrecognized task should be removed and a new
// task created in its place
// scheduled task should exist and be unrecognized
await retry.try(async () => {
const taskRecordLoaded = await getScheduledTask(RULE_ID);
expect(taskRecordLoaded.task.status).to.equal('unrecognized');
});
// enable the rule
await supertestWithoutAuth
.post(`${getUrlPrefix(``)}/api/alerting/rule/${RULE_ID}/_enable`)
.set('kbn-xsrf', 'foo');
await retry.try(async () => {
const response = await supertestWithoutAuth.get(
`${getUrlPrefix(``)}/api/alerting/rule/${RULE_ID}`
);
expect(response.status).to.eql(200);
expect(response.body.enabled).to.be(true);
});
// new scheduled task should exist with ID and status should not be unrecognized
const newTaskRecordLoaded = await getScheduledTask(RULE_ID);
expect(newTaskRecordLoaded.task.status).not.to.equal('unrecognized');
});
});
});
}

View file

@ -43,113 +43,119 @@ export default function createSnoozeRuleTests({ getService }: FtrProviderContext
const alertUtils = new AlertUtils({ space: Spaces.space1, supertestWithoutAuth });
it('should handle snooze rule request appropriately', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
.expect(200);
objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions');
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
enabled: false,
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
],
describe('handle snooze rule request appropriately', function () {
this.tags('skipFIPS');
it('should handle snooze rule request appropriately', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
.expect(200);
objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions');
const response = await alertUtils
.getSnoozeRequest(createdRule.id)
.send({ snooze_schedule: SNOOZE_SCHEDULE });
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
enabled: false,
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
],
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
expect(response.statusCode).to.eql(204);
expect(response.body).to.eql('');
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(updatedAlert.snooze_schedule.length).to.eql(1);
const { rRule, duration } = updatedAlert.snooze_schedule[0];
expect(rRule.dtstart).to.eql(NOW);
expect(duration).to.eql(SNOOZE_SCHEDULE.duration);
expect(updatedAlert.mute_all).to.eql(false);
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdRule.id,
const response = await alertUtils
.getSnoozeRequest(createdRule.id)
.send({ snooze_schedule: SNOOZE_SCHEDULE });
expect(response.statusCode).to.eql(204);
expect(response.body).to.eql('');
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(updatedAlert.snooze_schedule.length).to.eql(1);
const { rRule, duration } = updatedAlert.snooze_schedule[0];
expect(rRule.dtstart).to.eql(NOW);
expect(duration).to.eql(SNOOZE_SCHEDULE.duration);
expect(updatedAlert.mute_all).to.eql(false);
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdRule.id,
});
});
});
it('should handle snooze rule request appropriately when duration is -1', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
.expect(200);
objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions');
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
enabled: false,
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
],
describe('handle snooze rule request appropriately when duration is -1', function () {
this.tags('skipFIPS');
it('should handle snooze rule request appropriately when duration is -1', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
.expect(200);
objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions');
const response = await alertUtils.getSnoozeRequest(createdRule.id).send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
duration: -1,
},
});
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
enabled: false,
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
],
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
expect(response.statusCode).to.eql(204);
expect(response.body).to.eql('');
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(updatedAlert.snooze_schedule).to.eql([]);
expect(updatedAlert.mute_all).to.eql(true);
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdRule.id,
const response = await alertUtils.getSnoozeRequest(createdRule.id).send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
duration: -1,
},
});
expect(response.statusCode).to.eql(204);
expect(response.body).to.eql('');
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(updatedAlert.snooze_schedule).to.eql([]);
expect(updatedAlert.mute_all).to.eql(true);
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdRule.id,
});
});
});
@ -243,156 +249,162 @@ export default function createSnoozeRuleTests({ getService }: FtrProviderContext
expect(actionsDuring).to.be(0);
});
it('should prevent more than 5 schedules from being added to a rule', async () => {
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
enabled: false,
describe('prevent more than 5 schedules from being added to a rule', function () {
this.tags('skipFIPS');
it('should prevent more than 5 schedules from being added to a rule', async () => {
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
enabled: false,
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
// Creating 5 snooze schedules, using Promise.all is very flaky, therefore
// the schedules are being created 1 at a time
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
.expect(204);
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
// Creating 5 snooze schedules, using Promise.all is very flaky, therefore
// the schedules are being created 1 at a time
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
// Adding the 6th snooze schedule, should fail
const response = await alertUtils.getSnoozeRequest(createdRule.id).send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
await alertUtils
.getSnoozeRequest(createdRule.id)
.send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
})
.expect(204);
// Adding the 6th snooze schedule, should fail
const response = await alertUtils.getSnoozeRequest(createdRule.id).send({
snooze_schedule: {
...SNOOZE_SCHEDULE,
id: uuidv4(),
},
});
expect(response.statusCode).to.eql(400);
expect(response.body.message).to.eql('Rule cannot have more than 5 snooze schedules');
});
expect(response.statusCode).to.eql(400);
expect(response.body.message).to.eql('Rule cannot have more than 5 snooze schedules');
});
it('should clear the snooze after it expires', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
.expect(200);
objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions');
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
name: 'should not trigger actions when snoozed',
rule_type_id: 'test.patternFiring',
schedule: { interval: '1s' },
throttle: null,
notify_when: 'onActiveAlert',
params: {
pattern: { instance: arrayOfTrues(100) },
},
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
],
describe('clear the snooze after it expires', function () {
this.tags('skipFIPS');
it('should clear the snooze after it expires', async () => {
const { body: createdAction } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
.set('kbn-xsrf', 'foo')
.send({
name: 'MY action',
connector_type_id: 'test.noop',
config: {},
secrets: {},
})
)
.expect(200);
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
const dateStart = new Date().toISOString();
const snooze = {
...SNOOZE_SCHEDULE,
rRule: {
...SNOOZE_SCHEDULE.rRule,
// updating the dtstart to the current time because otherwise the snooze might be over already
dtstart: dateStart,
},
duration: 3000,
};
const response = await alertUtils.getSnoozeRequest(createdRule.id).send({
snooze_schedule: snooze,
});
expect(response.statusCode).to.eql(204);
expect(response.body).to.eql('');
await retry.try(async () => {
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(updatedAlert.snooze_schedule).to.eql([snooze]);
});
log.info('wait for snoozing to end');
await retry.try(async () => {
const { body: alertWithExpiredSnooze } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}`)
objectRemover.add(Spaces.space1.id, createdAction.id, 'action', 'actions');
const { body: createdRule } = await supertest
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
.set('kbn-xsrf', 'foo')
.send(
getTestRuleData({
name: 'should not trigger actions when snoozed',
rule_type_id: 'test.patternFiring',
schedule: { interval: '1s' },
throttle: null,
notify_when: 'onActiveAlert',
params: {
pattern: { instance: arrayOfTrues(100) },
},
actions: [
{
id: createdAction.id,
group: 'default',
params: {},
},
],
})
)
.expect(200);
expect(alertWithExpiredSnooze.snooze_schedule).to.eql([]);
});
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdRule.id,
objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting');
const dateStart = new Date().toISOString();
const snooze = {
...SNOOZE_SCHEDULE,
rRule: {
...SNOOZE_SCHEDULE.rRule,
// updating the dtstart to the current time because otherwise the snooze might be over already
dtstart: dateStart,
},
duration: 3000,
};
const response = await alertUtils.getSnoozeRequest(createdRule.id).send({
snooze_schedule: snooze,
});
expect(response.statusCode).to.eql(204);
expect(response.body).to.eql('');
await retry.try(async () => {
const { body: updatedAlert } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(updatedAlert.snooze_schedule).to.eql([snooze]);
});
log.info('wait for snoozing to end');
await retry.try(async () => {
const { body: alertWithExpiredSnooze } = await supertestWithoutAuth
.get(`${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdRule.id}`)
.set('kbn-xsrf', 'foo')
.expect(200);
expect(alertWithExpiredSnooze.snooze_schedule).to.eql([]);
});
// Ensure AAD isn't broken
await checkAAD({
supertest,
spaceId: Spaces.space1.id,
type: RULE_SAVED_OBJECT_TYPE,
id: createdRule.id,
});
});
});
});

View file

@ -22,7 +22,8 @@ export default function createSnoozeRuleTests({ getService }: FtrProviderContext
const supertest = getService('supertest');
const supertestWithoutAuth = getService('supertestWithoutAuth');
describe('unsnooze', () => {
describe('unsnooze', function () {
this.tags('skipFIPS');
const objectRemover = new ObjectRemover(supertest);
after(() => objectRemover.removeAll());

View file

@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('security (basic license)', function () {
this.tags('skipFIPS');
// Updates here should be mirrored in `./index.js` if tests
// should also run under a trial/platinum license.

View file

@ -9,7 +9,7 @@ import type { FtrProviderContext } from '../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('aiops basic license', function () {
this.tags(['aiops']);
this.tags(['aiops', 'skipFIPS']);
// The aiops API should return forbidden when called without a trial/platinum license.
loadTestFile(require.resolve('./permissions'));

View file

@ -72,17 +72,20 @@ export default function ApiTest({ getService }: FtrProviderContext) {
registry.when(
'fetching service anomalies with a basic license',
{ config: 'basic', archives: [] },
() => {
it('returns a 501', async () => {
const status = await statusOf(
getAnomalyCharts({
serviceName: 'a',
transactionType: 'request',
environment: 'ENVIRONMENT_ALL',
})
);
function () {
describe('should return a 501', function () {
this.tags('skipFIPS');
it('returns a 501', async function () {
const status = await statusOf(
getAnomalyCharts({
serviceName: 'a',
transactionType: 'request',
environment: 'ENVIRONMENT_ALL',
})
);
expect(status).to.eql(501);
expect(status).to.eql(501);
});
});
}
);

View file

@ -25,27 +25,30 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext)
const metadata = archives_metadata[archiveName];
registry.when('Service Map with a basic license', { config: 'basic', archives: [] }, () => {
it('is only be available to users with Platinum license (or higher)', async () => {
try {
await apmApiClient.readUser({
endpoint: `GET /internal/apm/service-map`,
params: {
query: {
start: metadata.start,
end: metadata.end,
environment: 'ENVIRONMENT_ALL',
describe('basic license', function () {
this.tags('skipFIPS');
it('is only be available to users with Platinum license (or higher)', async () => {
try {
await apmApiClient.readUser({
endpoint: `GET /internal/apm/service-map`,
params: {
query: {
start: metadata.start,
end: metadata.end,
environment: 'ENVIRONMENT_ALL',
},
},
},
});
});
expect(true).to.be(false);
} catch (e) {
const err = e as ApmApiError;
expect(err.res.status).to.be(403);
expectSnapshot(err.res.body.message).toMatchInline(
`"In order to access Service Maps, you must be subscribed to an Elastic Platinum license. With it, you'll have the ability to visualize your entire application stack along with your APM data."`
);
}
expect(true).to.be(false);
} catch (e) {
const err = e as ApmApiError;
expect(err.res.status).to.be(403);
expectSnapshot(err.res.body.message).toMatchInline(
`"In order to access Service Maps, you must be subscribed to an Elastic Platinum license. With it, you'll have the ability to visualize your entire application stack along with your APM data."`
);
}
});
});
});

View file

@ -78,7 +78,8 @@ export default function annotationApiTests({ getService }: FtrProviderContext) {
}
registry.when('Annotations with a basic license', { config: 'basic', archives: [] }, () => {
describe('when creating an annotation in basic license', () => {
describe('when creating an annotation in basic license', function () {
this.tags('skipFIPS');
it('fails with a 403 forbidden', async () => {
const err = await expectToReject<ApmApiError>(() =>
createAnnotation({

View file

@ -50,16 +50,19 @@ export default function apiTest({ getService }: FtrProviderContext) {
}
registry.when('ML jobs return a 403 for', { config: 'basic', archives: [] }, () => {
it('user without access', async () => {
await expectForbidden(apmApiClient.noAccessUser);
});
describe('basic', function () {
this.tags('skipFIPS');
it('user without access', async () => {
await expectForbidden(apmApiClient.noAccessUser);
});
it('read user', async () => {
await expectForbidden(apmApiClient.readUser);
});
it('read user', async () => {
await expectForbidden(apmApiClient.readUser);
});
it('write user', async () => {
await expectForbidden(apmApiClient.writeUser);
it('write user', async () => {
await expectForbidden(apmApiClient.writeUser);
});
});
});
}

View file

@ -18,21 +18,24 @@ export default function customLinksTests({ getService }: FtrProviderContext) {
const archiveName = 'apm_8.0.0';
registry.when('Custom links with a basic license', { config: 'basic', archives: [] }, () => {
it('returns a 403 forbidden', async () => {
const customLink = {
url: 'https://elastic.co',
label: 'with filters',
filters: [
{ key: 'service.name', value: 'baz' },
{ key: 'transaction.type', value: 'qux' },
],
} as CustomLink;
describe('basic', function () {
this.tags('skipFIPS');
it('returns a 403 forbidden', async () => {
const customLink = {
url: 'https://elastic.co',
label: 'with filters',
filters: [
{ key: 'service.name', value: 'baz' },
{ key: 'transaction.type', value: 'qux' },
],
} as CustomLink;
const err = await expectToReject<ApmApiError>(() => createCustomLink(customLink));
expect(err.res.status).to.be(403);
expectSnapshot(err.res.body.message).toMatchInline(
`"To create custom links, you must be subscribed to an Elastic Gold license or above. With it, you'll have the ability to create custom links to improve your workflow when analyzing your services."`
);
const err = await expectToReject<ApmApiError>(() => createCustomLink(customLink));
expect(err.res.status).to.be(403);
expectSnapshot(err.res.body.message).toMatchInline(
`"To create custom links, you must be subscribed to an Elastic Gold license or above. With it, you'll have the ability to create custom links to improve your workflow when analyzing your services."`
);
});
});
});

View file

@ -15,6 +15,8 @@ import {
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile, getService }: FtrProviderContext): void => {
describe('cases security and spaces enabled: basic', function () {
this.tags('skipFIPS');
before(async () => {
await createSpacesAndUsers(getService);
// once a user profile is created the only way to remove it is to delete the user and roles, so best to activate

View file

@ -11,6 +11,7 @@ import { createSpaces, deleteSpaces } from '../../../common/lib/authentication';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile, getService }: FtrProviderContext): void => {
describe('cases spaces only enabled: trial', function () {
this.tags('skipFIPS');
before(async () => {
await createSpaces(getService);
});

View file

@ -14,7 +14,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
const appsMenu = getService('appsMenu');
const managementMenu = getService('managementMenu');
describe('security', () => {
describe('security', function () {
this.tags('skipFIPS');
before(async () => {
await PageObjects.common.navigateToApp('home');
});

View file

@ -221,6 +221,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
describe('Readonly API key', function () {
this.tags('skipFIPS');
before(async () => {
await security.role.create('read_security_role', {
elasticsearch: {

View file

@ -38,10 +38,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should not render the "Data" section', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
describe('"Data" section', function () {
this.tags('skipFIPS');
it('should not render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
});
});
});
@ -57,22 +60,25 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should render the "Data" section with CCR', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
expect(sections).to.have.length(3);
expect(sections[1]).to.eql({
sectionId: 'data',
sectionLinks: [
'index_management',
'index_lifecycle_management',
'snapshot_restore',
'rollup_jobs',
'transform',
'cross_cluster_replication',
'remote_clusters',
'migrate_data',
],
describe('"Data" section with CCR', function () {
this.tags('skipFIPS');
it('should render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
expect(sections).to.have.length(3);
expect(sections[1]).to.eql({
sectionId: 'data',
sectionLinks: [
'index_management',
'index_lifecycle_management',
'snapshot_restore',
'rollup_jobs',
'transform',
'cross_cluster_replication',
'remote_clusters',
'migrate_data',
],
});
});
});
});

View file

@ -38,10 +38,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should not render the "Data" section', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
describe('"Data" section', function () {
this.tags('skipFIPS');
it('should not render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
});
});
});
@ -57,15 +60,19 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should render the "Data" section with ILM', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
// Changed sections to have a length of 2 because of
// https://github.com/elastic/kibana/pull/121262
expect(sections).to.have.length(2);
expect(sections[0]).to.eql({
sectionId: 'data',
sectionLinks: ['index_lifecycle_management'],
describe('"Data" section with ILM', function () {
this.tags('skipFIPS');
it('should render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
// Changed sections to have a length of 2 because of
// https://github.com/elastic/kibana/pull/121262
expect(sections).to.have.length(2);
expect(sections[0]).to.eql({
sectionId: 'data',
sectionLinks: ['index_lifecycle_management'],
});
});
});
});

View file

@ -38,10 +38,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should not render the "Data" section', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
describe('"Data" section', function () {
this.tags('skipFIPS');
it('should not render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
});
});
});
@ -57,16 +60,19 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should render the "Data" section with index management', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
describe('"Data" section with index management', function () {
this.tags('skipFIPS');
it('should render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
// The index_management_user has been given permissions to advanced settings for Stack Management Tests.
// https://github.com/elastic/kibana/pull/113078/
expect(sections).to.have.length(2);
expect(sections[0]).to.eql({
sectionId: 'data',
sectionLinks: ['index_management', 'data_quality', 'transform'],
// The index_management_user has been given permissions to advanced settings for Stack Management Tests.
// https://github.com/elastic/kibana/pull/113078/
expect(sections).to.have.length(2);
expect(sections[0]).to.eql({
sectionId: 'data',
sectionLinks: ['index_management', 'data_quality', 'transform'],
});
});
});
});

View file

@ -39,10 +39,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should not render the "Ingest" section', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
describe('"Ingest" section', function () {
this.tags('skipFIPS');
it('should not render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
});
});
});
@ -58,15 +61,18 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should render the "Ingest" section with ingest pipelines', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
// We gave the ingest pipelines user access to advanced settings to allow them to use ingest pipelines.
// See https://github.com/elastic/kibana/pull/102409/
expect(sections).to.have.length(2);
expect(sections[0]).to.eql({
sectionId: 'ingest',
sectionLinks: ['ingest_pipelines'],
describe('"Ingest" section with ingest pipelines', function () {
this.tags('skipFIPS');
it('should render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
// We gave the ingest pipelines user access to advanced settings to allow them to use ingest pipelines.
// See https://github.com/elastic/kibana/pull/102409/
expect(sections).to.have.length(2);
expect(sections[0]).to.eql({
sectionId: 'ingest',
sectionLinks: ['ingest_pipelines'],
});
});
});
});

View file

@ -276,27 +276,30 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(hasPrompt).to.eql(false);
});
it('should not display add-to-dashboard options', async () => {
await visualize.navigateToNewVisualization();
await visualize.clickVisType('lens');
await lens.goToTimeRange();
describe('add-to-dashboard options', function () {
this.tags('skipFIPS');
it('should not display', async () => {
await visualize.navigateToNewVisualization();
await visualize.clickVisType('lens');
await lens.goToTimeRange();
await lens.configureDimension({
dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
operation: 'average',
field: 'bytes',
await lens.configureDimension({
dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
operation: 'average',
field: 'bytes',
});
await lens.switchToVisualization('lnsLegacyMetric');
await lens.waitForVisualization('legacyMtrVis');
await lens.assertLegacyMetric('Average of bytes', '5,727.322');
await lens.waitForVisualization('legacyMtrVis');
await testSubjects.click('lnsApp_saveButton');
const hasOptions = await testSubjects.exists('add-to-dashboard-options');
expect(hasOptions).to.eql(false);
});
await lens.switchToVisualization('lnsLegacyMetric');
await lens.waitForVisualization('legacyMtrVis');
await lens.assertLegacyMetric('Average of bytes', '5,727.322');
await lens.waitForVisualization('legacyMtrVis');
await testSubjects.click('lnsApp_saveButton');
const hasOptions = await testSubjects.exists('add-to-dashboard-options');
expect(hasOptions).to.eql(false);
});
});
@ -322,27 +325,30 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
expect(hasPrompt).to.eql(false);
});
it('should not display add-to-dashboard options', async () => {
await visualize.navigateToNewVisualization();
await visualize.clickVisType('lens');
await lens.goToTimeRange();
describe('add-to-dashboard options', function () {
this.tags('skipFIPS');
it('should not display', async () => {
await visualize.navigateToNewVisualization();
await visualize.clickVisType('lens');
await lens.goToTimeRange();
await lens.configureDimension({
dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
operation: 'average',
field: 'bytes',
await lens.configureDimension({
dimension: 'lnsXY_yDimensionPanel > lns-empty-dimension',
operation: 'average',
field: 'bytes',
});
await lens.switchToVisualization('lnsLegacyMetric');
await lens.waitForVisualization('legacyMtrVis');
await lens.assertLegacyMetric('Average of bytes', '5,727.322');
await lens.waitForVisualization('legacyMtrVis');
await testSubjects.click('lnsApp_saveButton');
const hasOptions = await testSubjects.exists('add-to-dashboard-options');
expect(hasOptions).to.eql(false);
});
await lens.switchToVisualization('lnsLegacyMetric');
await lens.waitForVisualization('legacyMtrVis');
await lens.assertLegacyMetric('Average of bytes', '5,727.322');
await lens.waitForVisualization('legacyMtrVis');
await testSubjects.click('lnsApp_saveButton');
const hasOptions = await testSubjects.exists('add-to-dashboard-options');
expect(hasOptions).to.eql(false);
});
});
});

View file

@ -38,10 +38,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should not render the "Stack" section', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
describe('"Stack" section', function () {
this.tags('skipFIPS');
it('should not render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
});
});
});
@ -58,7 +61,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
});
describe('[SkipCloud] global dashboard with license management user and upgrade assistant : skip cloud', function () {
this.tags('skipCloud');
this.tags(['skipCloud', 'skipFIPS']);
it('should render the "Stack" section with License Management and Upgrade Assistant', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();

View file

@ -25,7 +25,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await kibanaServer.savedObjects.cleanStandardList();
});
describe('global all privileges (aka kibana_admin)', () => {
describe('global all privileges (aka kibana_admin)', function () {
before(async () => {
await security.testUser.setRoles(['kibana_admin']);
});
@ -38,10 +38,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should not render the "Ingest" section', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
describe('"Ingest section"', function () {
this.tags('skipFIPS');
it('should not render', async function () {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
});
});
});
@ -57,13 +60,16 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should render the "Ingest" section with Logstash Pipelines', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
expect(sections).to.have.length(1);
expect(sections[0]).to.eql({
sectionId: 'ingest',
sectionLinks: ['pipelines'],
describe('"Ingest" section with Logstash Pipelines', function () {
this.tags('skipFIPS');
it('should render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
expect(sections).to.have.length(1);
expect(sections[0]).to.eql({
sectionId: 'ingest',
sectionLinks: ['pipelines'],
});
});
});
});

View file

@ -16,7 +16,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
const managementMenu = getService('managementMenu');
const testSubjects = getService('testSubjects');
describe('security', () => {
describe('security', function () {
this.tags('skipFIPS');
before(async () => {
await kibanaServer.savedObjects.cleanStandardList();
await PageObjects.common.navigateToApp('home');
@ -26,7 +27,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await kibanaServer.savedObjects.cleanStandardList();
});
describe('no management privileges', () => {
describe('no management privileges', function () {
this.tags('skipFIPS');
before(async () => {
await security.testUser.setRoles(['global_dashboard_read']);
});

View file

@ -39,7 +39,8 @@ export default function ({ getService, getPageObjects }) {
});
});
describe('without write permission', () => {
describe('without write permission', function () {
this.tags('skipFIPS');
before(async () => {
await security.testUser.setRoles(
['global_maps_read', 'global_visualize_all', 'test_logstash_reader'],

View file

@ -38,10 +38,13 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should not render the "Stack" section', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
describe('"Stack" section', function () {
this.tags('skipFIPS');
it('should not render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
});
});
});
@ -57,21 +60,24 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should render the "Data" section with Remote Clusters', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
expect(sections).to.have.length(3);
expect(sections[1]).to.eql({
sectionId: 'data',
sectionLinks: [
'index_management',
'index_lifecycle_management',
'snapshot_restore',
'rollup_jobs',
'transform',
'remote_clusters',
'migrate_data',
],
describe('"Data" section with Remote Clusters', function () {
this.tags('skipFIPS');
it('should render', async () => {
await PageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
expect(sections).to.have.length(3);
expect(sections[1]).to.eql({
sectionId: 'data',
sectionLinks: [
'index_management',
'index_lifecycle_management',
'snapshot_restore',
'rollup_jobs',
'transform',
'remote_clusters',
'migrate_data',
],
});
});
});
});

View file

@ -39,10 +39,14 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should not render the "Stack" section', async () => {
await pageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
describe('"Stack" section', function () {
this.tags('skipFIPS');
it('should not render', async () => {
await pageObjects.common.navigateToApp('management');
const sections = (await managementMenu.getSections()).map((section) => section.sectionId);
expect(sections).to.eql(['insightsAndAlerting', 'kibana']);
});
});
});
@ -58,13 +62,16 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
expect(links.map((link) => link.text)).to.contain('Stack Management');
});
it('should render the "Data" section with Transform', async () => {
await pageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
expect(sections).to.have.length(1);
expect(sections[0]).to.eql({
sectionId: 'data',
sectionLinks: ['transform'],
describe('"Data" section with Transform', function () {
this.tags('skipFIPS');
it('should render', async () => {
await pageObjects.common.navigateToApp('management');
const sections = await managementMenu.getSections();
expect(sections).to.have.length(1);
expect(sections[0]).to.eql({
sectionId: 'data',
sectionLinks: ['transform'],
});
});
});
});

View file

@ -12,7 +12,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
const ml = getService('ml');
describe('machine learning basic license - data visualizer - group 1', function () {
this.tags(['skipFirefox', 'ml']);
this.tags(['skipFirefox', 'ml', 'skipFIPS']);
before(async () => {
await ml.securityCommon.createMlRoles();

View file

@ -12,7 +12,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
const ml = getService('ml');
describe('machine learning basic license - data visualizer - group 2', function () {
this.tags(['skipFirefox', 'ml']);
this.tags(['skipFirefox', 'ml', 'skipFIPS']);
before(async () => {
await ml.securityCommon.createMlRoles();

View file

@ -12,7 +12,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
const ml = getService('ml');
describe('machine learning basic license - data visualizer - group 3', function () {
this.tags(['skipFirefox', 'ml']);
this.tags(['skipFirefox', 'ml', 'skipFIPS']);
before(async () => {
await ml.securityCommon.createMlRoles();

View file

@ -12,7 +12,7 @@ export default function ({ getService }: FtrProviderContext) {
const ml = getService('ml');
describe('index based actions panel on basic license', function () {
this.tags(['ml']);
this.tags(['ml', 'skipFIPS']);
const indexPatternName = 'ft_farequote';
const savedSearch = 'ft_farequote_kuery';

View file

@ -20,6 +20,7 @@ export default function ({ getService }: FtrProviderContext) {
];
describe('for user with full ML access', function () {
this.tags('skipFIPS');
for (const testUser of testUsers) {
describe(`(${testUser.user})`, function () {
const ecIndexPattern = 'ft_module_sample_ecommerce';

View file

@ -20,6 +20,7 @@ export default function ({ getService }: FtrProviderContext) {
];
describe('for user with read ML access', function () {
this.tags('skipFIPS');
for (const testUser of testUsers) {
describe(`(${testUser.user})`, function () {
const ecIndexPattern = 'ft_module_sample_ecommerce';

View file

@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('transform basic license', function () {
this.tags(['skipFirefox', 'transform']);
this.tags(['skipFirefox', 'transform', 'skipFIPS']);
// The transform UI should work the same as with a trial license
loadTestFile(require.resolve('../../../../functional/apps/transform/actions'));

View file

@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('transform basic license', function () {
this.tags(['skipFirefox', 'transform']);
this.tags(['skipFirefox', 'transform', 'skipFIPS']);
// The transform UI should work the same as with a trial license
loadTestFile(

View file

@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('transform basic license', function () {
this.tags(['skipFirefox', 'transform']);
this.tags(['skipFirefox', 'transform', 'skipFIPS']);
// The transform UI should work the same as with a trial license
loadTestFile(

View file

@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('transform basic license', function () {
this.tags(['skipFirefox', 'transform']);
this.tags(['skipFirefox', 'transform', 'skipFIPS']);
// The transform UI should work the same as with a trial license
loadTestFile(require.resolve('../../../../functional/apps/transform/edit_clone'));

View file

@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('transform basic license', function () {
this.tags(['skipFirefox', 'transform']);
this.tags(['skipFirefox', 'transform', 'skipFIPS']);
// The transform UI should work the same as with a trial license
loadTestFile(require.resolve('../../../../functional/apps/transform/feature_controls'));

View file

@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('transform basic license', function () {
this.tags(['skipFirefox', 'transform']);
this.tags(['skipFirefox', 'transform', 'skipFIPS']);
// The transform UI should work the same as with a trial license
loadTestFile(require.resolve('../../../../functional/apps/transform/permissions'));

View file

@ -35,7 +35,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
});
});
describe('Loads the app with actions but not alerting privilege', () => {
describe('Loads the app with actions but not alerting privilege', function () {
this.tags('skipFIPS');
before(async () => {
await security.testUser.setRoles(['only_actions_role']);
});

View file

@ -50,32 +50,36 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
expect(headingText).to.be('Alerts');
});
it('Shows only allowed feature filters', async () => {
await pageObjects.common.navigateToUrl(
'management',
'insightsAndAlerting/triggersActionsAlerts',
{
shouldUseHashForSubUrl: false,
}
);
describe('feature filters', function () {
this.tags('skipFIPS');
it('Shows only allowed feature filters', async () => {
await pageObjects.common.navigateToUrl(
'management',
'insightsAndAlerting/triggersActionsAlerts',
{
shouldUseHashForSubUrl: false,
}
);
await pageObjects.header.waitUntilLoadingHasFinished();
await pageObjects.header.waitUntilLoadingHasFinished();
await retry.try(async () => {
if (!(await testSubjects.exists('queryBarMenuPanel'))) {
await pageObjects.triggersActionsUI.clickAlertsPageShowQueryMenuButton();
}
const quickFilters = await pageObjects.triggersActionsUI.getAlertsPageQuickFilters();
const solutionFilters = getSolutionNamesFromFilters(quickFilters);
expect(solutionFilters).to.have.length(2);
expect(solutionFilters[0]).to.equal('Stack');
// Observability is included because of multi-consumer rules
expect(solutionFilters[1]).to.equal('Observability');
await retry.try(async () => {
if (!(await testSubjects.exists('queryBarMenuPanel'))) {
await pageObjects.triggersActionsUI.clickAlertsPageShowQueryMenuButton();
}
const quickFilters = await pageObjects.triggersActionsUI.getAlertsPageQuickFilters();
const solutionFilters = getSolutionNamesFromFilters(quickFilters);
expect(solutionFilters).to.have.length(2);
expect(solutionFilters[0]).to.equal('Stack');
// Observability is included because of multi-consumer rules
expect(solutionFilters[1]).to.equal('Observability');
});
});
});
});
describe('Loads the page with actions but not alerting privilege', () => {
describe('Loads the page with actions but not alerting privilege', function () {
this.tags('skipFIPS');
beforeEach(async () => {
await security.testUser.restoreDefaults();
await security.testUser.setRoles(['only_actions_role']);

View file

@ -13,7 +13,8 @@ export default function ({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
describe('Info', () => {
describe('GET /api/licensing/info', () => {
describe('GET /api/licensing/info', function () {
this.tags('skipFIPS');
it('returns licensing information', async () => {
const response = await supertest.get('/api/licensing/info').expect(200);

View file

@ -17,7 +17,8 @@ export default function (ftrContext: FtrProviderContext) {
const scenario = createScenario(ftrContext);
describe('changes in license types', () => {
describe('changes in license types', function () {
this.tags('skipFIPS');
after(async () => {
await scenario.teardown();
});

View file

@ -10,6 +10,7 @@ import { FtrProviderContext } from '../../common/ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default function observabilityApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
describe('Observability specs (basic)', function () {
this.tags('skipFIPS');
loadTestFile(require.resolve('./annotations'));
});
}

View file

@ -24,7 +24,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
const kibanaServer = getService('kibanaServer');
describe('observability security feature controls', function () {
this.tags(['skipFirefox']);
this.tags(['skipFirefox', 'skipFIPS']);
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/cases/default');
});
@ -90,7 +90,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
});
});
describe('observability cases read-only privileges', () => {
describe('observability cases read-only privileges', function () {
this.tags('skipFIPS');
before(async () => {
await esArchiver.load('x-pack/test/functional/es_archives/infra/metrics_and_logs');
await observability.users.setTestUserRole(
@ -143,7 +144,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
});
});
describe('no observability privileges', () => {
describe('no observability privileges', function () {
this.tags('skipFIPS');
before(async () => {
await observability.users.setTestUserRole({
elasticsearch: { cluster: [], indices: [], run_as: [] },

View file

@ -71,6 +71,7 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => {
});
describe('When user has read permissions for cases', () => {
this.tags('skipFIPS');
before(async () => {
await observability.users.setTestUserRole(
observability.users.defineBasicObservabilityRole({

View file

@ -194,7 +194,8 @@ export default ({ getService }: FtrProviderContext) => {
});
});
describe('User permissions', () => {
describe('User permissions', function () {
this.tags('skipFIPS');
before(async () => {
await observability.alerts.common.navigateToRuleDetailsByRuleId(logThresholdRuleId);
});

View file

@ -137,42 +137,49 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => {
await observability.users.restoreDefaultTestUserRole();
});
it('Allows ES query rules to be created by users with only infrastructure feature enabled', async () => {
await observability.users.setTestUserRole(
observability.users.defineBasicObservabilityRole({
infrastructure: ['all'],
})
);
await navigateAndOpenCreateRuleFlyout();
await selectAndFillInEsQueryRule(ruleName);
describe('only infrastructure feature enabled', function () {
this.tags('skipFIPS');
it('Allows ES query rules to be created by users with only infrastructure feature enabled', async () => {
await observability.users.setTestUserRole(
observability.users.defineBasicObservabilityRole({
infrastructure: ['all'],
})
);
await navigateAndOpenCreateRuleFlyout();
await selectAndFillInEsQueryRule(ruleName);
await testSubjects.click('saveRuleButton');
await testSubjects.click('saveRuleButton');
await PageObjects.header.waitUntilLoadingHasFinished();
await PageObjects.header.waitUntilLoadingHasFinished();
const tableRows = await find.allByCssSelector('.euiTableRow');
const rows = await getRulesList(tableRows);
expect(rows.length).to.be(1);
expect(rows[0].name).to.contain(ruleName);
const tableRows = await find.allByCssSelector('.euiTableRow');
const rows = await getRulesList(tableRows);
expect(rows.length).to.be(1);
expect(rows[0].name).to.contain(ruleName);
});
});
it('allows ES query rules to be created by users with only logs feature enabled', async () => {
await observability.users.setTestUserRole(
observability.users.defineBasicObservabilityRole({
logs: ['all'],
})
);
await navigateAndOpenCreateRuleFlyout();
await selectAndFillInEsQueryRule(ruleName);
describe('only logs feature enabled', function () {
this.tags('skipFIPS');
await testSubjects.click('saveRuleButton');
it('allows ES query rules to be created by users with only logs feature enabled', async () => {
await observability.users.setTestUserRole(
observability.users.defineBasicObservabilityRole({
logs: ['all'],
})
);
await navigateAndOpenCreateRuleFlyout();
await selectAndFillInEsQueryRule(ruleName);
await PageObjects.header.waitUntilLoadingHasFinished();
await testSubjects.click('saveRuleButton');
const tableRows = await find.allByCssSelector('.euiTableRow');
const rows = await getRulesList(tableRows);
expect(rows.length).to.be(1);
expect(rows[0].name).to.contain(ruleName);
await PageObjects.header.waitUntilLoadingHasFinished();
const tableRows = await find.allByCssSelector('.euiTableRow');
const rows = await getRulesList(tableRows);
expect(rows.length).to.be(1);
expect(rows[0].name).to.contain(ruleName);
});
});
it('Should allow the user to select consumers when creating ES query rules', async () => {
@ -313,51 +320,57 @@ export default ({ getService, getPageObjects }: FtrProviderContext) => {
);
});
it(`shows the no permission prompt when the user has no permissions`, async () => {
// We kept this test to make sure that the stack management rule page
// is showing the right prompt corresponding to the right privileges.
// Knowing that o11y alert page won't come up if you do not have any
// kind of privileges to o11y
await observability.users.setTestUserRole({
elasticsearch: {
cluster: [],
indices: [],
run_as: [],
},
kibana: [
{
base: [],
feature: {
discover: ['read'],
},
spaces: ['*'],
describe('permission prompt', function () {
this.tags('skipFIPS');
it(`shows the no permission prompt when the user has no permissions`, async () => {
// We kept this test to make sure that the stack management rule page
// is showing the right prompt corresponding to the right privileges.
// Knowing that o11y alert page won't come up if you do not have any
// kind of privileges to o11y
await observability.users.setTestUserRole({
elasticsearch: {
cluster: [],
indices: [],
run_as: [],
},
],
kibana: [
{
base: [],
feature: {
discover: ['read'],
},
spaces: ['*'],
},
],
});
await observability.alerts.common.navigateToRulesPage();
await retry.waitFor(
'No permissions prompt',
async () => await testSubjects.exists('noPermissionPrompt')
);
await observability.users.restoreDefaultTestUserRole();
});
await observability.alerts.common.navigateToRulesPage();
await retry.waitFor(
'No permissions prompt',
async () => await testSubjects.exists('noPermissionPrompt')
);
await observability.users.restoreDefaultTestUserRole();
});
it(`shows the rules list in read-only mode when the user only has read permissions`, async () => {
await observability.users.setTestUserRole(
observability.users.defineBasicObservabilityRole({
logs: ['read'],
})
);
await observability.alerts.common.navigateToRulesPage();
await retry.waitFor(
'Read-only rules list is visible',
async () => await testSubjects.exists('rulesList')
);
await retry.waitFor(
'Create rule button is disabled',
async () => !(await testSubjects.isEnabled('createRuleButton'))
);
await observability.users.restoreDefaultTestUserRole();
describe('rules list', function () {
this.tags('skipFIPS');
it(`shows the rules list in read-only mode when the user only has read permissions`, async () => {
await observability.users.setTestUserRole(
observability.users.defineBasicObservabilityRole({
logs: ['read'],
})
);
await observability.alerts.common.navigateToRulesPage();
await retry.waitFor(
'Read-only rules list is visible',
async () => await testSubjects.exists('rulesList')
);
await retry.waitFor(
'Create rule button is disabled',
async () => !(await testSubjects.isEnabled('createRuleButton'))
);
await observability.users.restoreDefaultTestUserRole();
});
});
});
});

View file

@ -10,6 +10,7 @@ import { FtrProviderContext } from '../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default function ({ loadTestFile, getService }: FtrProviderContext) {
describe('Reporting API Integration Tests with Security disabled', function () {
this.tags('skipFIPS');
before(async () => {
const reportingAPI = getService('reportingAPI');
await reportingAPI.logTaskManagerHealth();

View file

@ -10,6 +10,7 @@ import { FtrProviderContext } from '../ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default function ({ loadTestFile, getService }: FtrProviderContext) {
describe('Reporting Functional Tests with Security disabled', function () {
this.tags('skipFIPS');
before(async () => {
const reportingAPI = getService('reportingAPI');
await reportingAPI.logTaskManagerHealth();

View file

@ -11,6 +11,7 @@ import { createSpaces, deleteSpaces } from '../../../common/lib/authentication';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile, getService }: FtrProviderContext): void => {
describe('rule registry spaces only: trial', function () {
this.tags('skipFIPS');
before(async () => {
await createSpaces(getService);
});

View file

@ -11,6 +11,7 @@ import { createSpaces, deleteSpaces } from '../../../common/lib/authentication';
// eslint-disable-next-line import/no-default-export
export default ({ loadTestFile, getService }: FtrProviderContext): void => {
describe('rule registry spaces only: trial', function () {
this.tags('skipFIPS');
before(async () => {
await createSpaces(getService);
});

View file

@ -39,7 +39,6 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions)
junit: {
reportName: 'X-Pack Saved Object API Integration Tests -- ' + name,
},
esTestCluster: {
...config.xpack.api.get('esTestCluster'),
license,

View file

@ -11,8 +11,14 @@ import { FtrProviderContext } from '../../common/ftr_provider_context';
export default function ({ getService, loadTestFile }: FtrProviderContext) {
const es = getService('es');
const supertest = getService('supertest');
const config = getService('config');
const basic = config.get('esTestCluster.license') === 'basic';
describe('saved objects security and spaces enabled', function () {
if (basic) {
this.tags('skipFIPS');
}
before(async () => {
await createUsersAndRoles(es, supertest);
});

View file

@ -9,6 +9,7 @@ import { FtrProviderContext } from '../../common/ftr_provider_context';
export default function ({ loadTestFile }: FtrProviderContext) {
describe('saved objects spaces only enabled', function () {
this.tags('skipFIPS');
loadTestFile(require.resolve('./bulk_create'));
loadTestFile(require.resolve('./bulk_get'));
loadTestFile(require.resolve('./bulk_resolve'));

View file

@ -298,58 +298,61 @@ export default function ({ getService }: FtrProviderContext) {
.expect(401);
});
it('only super users should be able to invalidate sessions', async function () {
const basicSessionCookie = await loginWithBasic(notSuperuserTestUser);
const samlSessionCookie = await loginWithSAML();
describe('only super users', function () {
this.tags('skipFIPS');
it('should be able to invalidate sessions', async function () {
const basicSessionCookie = await loginWithBasic(notSuperuserTestUser);
const samlSessionCookie = await loginWithSAML();
// User without a superuser role shouldn't be able to invalidate sessions.
await supertest
.post('/api/security/session/_invalidate')
.set('kbn-xsrf', 'xxx')
.auth(notSuperuserTestUser.username, notSuperuserTestUser.password)
.send({ match: 'all' })
.expect(403);
await supertest
.post('/api/security/session/_invalidate')
.set('kbn-xsrf', 'xxx')
.auth(notSuperuserTestUser.username, notSuperuserTestUser.password)
.send({ match: 'query', query: { provider: { type: 'basic' } } })
.expect(403);
await supertest
.post('/api/security/session/_invalidate')
.set('kbn-xsrf', 'xxx')
.auth(notSuperuserTestUser.username, notSuperuserTestUser.password)
.send({
match: 'query',
query: { provider: { type: 'basic' }, username: notSuperuserTestUser.username },
})
.expect(403);
// User without a superuser role shouldn't be able to invalidate sessions.
await supertest
.post('/api/security/session/_invalidate')
.set('kbn-xsrf', 'xxx')
.auth(notSuperuserTestUser.username, notSuperuserTestUser.password)
.send({ match: 'all' })
.expect(403);
await supertest
.post('/api/security/session/_invalidate')
.set('kbn-xsrf', 'xxx')
.auth(notSuperuserTestUser.username, notSuperuserTestUser.password)
.send({ match: 'query', query: { provider: { type: 'basic' } } })
.expect(403);
await supertest
.post('/api/security/session/_invalidate')
.set('kbn-xsrf', 'xxx')
.auth(notSuperuserTestUser.username, notSuperuserTestUser.password)
.send({
match: 'query',
query: { provider: { type: 'basic' }, username: notSuperuserTestUser.username },
})
.expect(403);
await checkSessionCookie(basicSessionCookie, notSuperuserTestUser.username, {
type: 'basic',
name: 'basic1',
await checkSessionCookie(basicSessionCookie, notSuperuserTestUser.username, {
type: 'basic',
name: 'basic1',
});
await checkSessionCookie(samlSessionCookie, 'a@b.c', { type: 'saml', name: 'saml1' });
// With superuser role, it should be possible now.
await security.testUser.setRoles(['superuser']);
await supertest
.post('/api/security/session/_invalidate')
.set('kbn-xsrf', 'xxx')
.auth(notSuperuserTestUser.username, notSuperuserTestUser.password)
.send({ match: 'all' })
.expect(200, { total: 2 });
await supertest
.get('/internal/security/me')
.set('kbn-xsrf', 'xxx')
.set('Cookie', basicSessionCookie.cookieString())
.expect(401);
await supertest
.get('/internal/security/me')
.set('kbn-xsrf', 'xxx')
.set('Cookie', samlSessionCookie.cookieString())
.expect(401);
});
await checkSessionCookie(samlSessionCookie, 'a@b.c', { type: 'saml', name: 'saml1' });
// With superuser role, it should be possible now.
await security.testUser.setRoles(['superuser']);
await supertest
.post('/api/security/session/_invalidate')
.set('kbn-xsrf', 'xxx')
.auth(notSuperuserTestUser.username, notSuperuserTestUser.password)
.send({ match: 'all' })
.expect(200, { total: 2 });
await supertest
.get('/internal/security/me')
.set('kbn-xsrf', 'xxx')
.set('Cookie', basicSessionCookie.cookieString())
.expect(401);
await supertest
.get('/internal/security/me')
.set('kbn-xsrf', 'xxx')
.set('Cookie', samlSessionCookie.cookieString())
.expect(401);
});
});
}

View file

@ -16,6 +16,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
const retry = getService('retry');
describe('Insecure Cluster Warning', function () {
this.tags('skipFIPS');
before(async () => {
await es.indices.create({ index: 'my-index-001' });
await es.index({ index: 'my-index-001', body: { foo: 'bar' } });

View file

@ -31,7 +31,7 @@ export default ({ getService }: FtrProviderContext) => {
const auditbeatPath = dataPathBuilder.getPath('auditbeat/hosts');
describe('create_ml_rules', () => {
describe('Creating Machine Learning rules', () => {
describe('Creating Machine Learning rules', function () {
before(async () => {
await esArchiver.load(auditbeatPath);
});
@ -49,20 +49,25 @@ export default ({ getService }: FtrProviderContext) => {
await deleteAllRules(supertest, log);
});
it('@ess should give a 403 when trying to create a single Machine Learning rule since the license is basic', async () => {
const { body } = await supertest
.post(DETECTION_ENGINE_RULES_URL)
.set('kbn-xsrf', 'true')
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.send(getSimpleMlRule())
.expect(403);
describe('@ess', function () {
/* Wrapped in `describe` block, because `this.tags` only works in `describe` blocks */
this.tags('skipFIPS');
it('should give a 403 when trying to create a single Machine Learning rule since the license is basic', async function () {
const { body } = await supertest
.post(DETECTION_ENGINE_RULES_URL)
.set('kbn-xsrf', 'true')
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.send(getSimpleMlRule())
.expect(403);
const bodyToCompare = removeServerGeneratedProperties(body);
expect(bodyToCompare).toEqual({
message: 'Your license does not support machine learning. Please upgrade your license.',
status_code: 403,
const bodyToCompare = removeServerGeneratedProperties(body);
expect(bodyToCompare).toEqual({
message: 'Your license does not support machine learning. Please upgrade your license.',
status_code: 403,
});
});
});
it('@serverless should give a 200 when trying to create a single Machine Learning rule since the license is essentials', async () => {
const { body } = await supertest
.post(DETECTION_ENGINE_RULES_URL)

View file

@ -99,17 +99,21 @@ export default ({ getService }: FtrProviderContext) => {
expect(patchedRule).toMatchObject(expectedRule);
});
it('@skipInServerless should return a "403 forbidden" using a rule_id of type "machine learning"', async () => {
await createRule(supertest, log, getSimpleRule('rule-1'));
describe('@skipInServerless ', function () {
/* Wrapped in `describe` block, because `this.tags` only works in `describe` blocks */
this.tags('skipFIPS');
it('should return a "403 forbidden" using a rule_id of type "machine learning"', async () => {
await createRule(supertest, log, getSimpleRule('rule-1'));
// patch a simple rule's type to machine learning
const { body } = await securitySolutionApi
.patchRule({ body: { rule_id: 'rule-1', type: 'machine_learning' } })
.expect(403);
// patch a simple rule's type to machine learning
const { body } = await securitySolutionApi
.patchRule({ body: { rule_id: 'rule-1', type: 'machine_learning' } })
.expect(403);
expect(body).toEqual({
message: 'Your license does not support machine learning. Please upgrade your license.',
status_code: 403,
expect(body).toEqual({
message: 'Your license does not support machine learning. Please upgrade your license.',
status_code: 403,
});
});
});

View file

@ -102,20 +102,24 @@ export default ({ getService }: FtrProviderContext) => {
expect(updatedRule).toMatchObject(expectedRule);
});
it('@skipInServerless should return a 403 forbidden if it is a machine learning job', async () => {
await createRule(supertest, log, getSimpleRule('rule-1'));
describe('@skipInServerless', function () {
/* Wrapped in `describe` block, because `this.tags` only works in `describe` blocks */
this.tags('skipFIPS');
it('should return a 403 forbidden if it is a machine learning job', async () => {
await createRule(supertest, log, getSimpleRule('rule-1'));
// update a simple rule's type to try to be a machine learning job type
const updatedRule = getSimpleMlRuleUpdate('rule-1');
updatedRule.rule_id = 'rule-1';
updatedRule.name = 'some other name';
delete updatedRule.id;
// update a simple rule's type to try to be a machine learning job type
const updatedRule = getSimpleMlRuleUpdate('rule-1');
updatedRule.rule_id = 'rule-1';
updatedRule.name = 'some other name';
delete updatedRule.id;
const { body } = await securitySolutionApi.updateRule({ body: updatedRule }).expect(403);
const { body } = await securitySolutionApi.updateRule({ body: updatedRule }).expect(403);
expect(body).toEqual({
message: 'Your license does not support machine learning. Please upgrade your license.',
status_code: 403,
expect(body).toEqual({
message: 'Your license does not support machine learning. Please upgrade your license.',
status_code: 403,
});
});
});

Some files were not shown because too many files have changed in this diff Show more