mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[ML] Add job audit messages API integration tests (#110793)
This commit is contained in:
parent
1205ba4ce0
commit
0ae7455377
6 changed files with 277 additions and 1 deletions
1
x-pack/plugins/ml/.gitignore
vendored
1
x-pack/plugins/ml/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
routes_doc
|
||||
server/routes/apidoc_scripts/header.md
|
||||
|
|
|
@ -101,7 +101,7 @@ export function jobAuditMessagesRoutes({ router, routeGuard }: RouteInitializati
|
|||
/**
|
||||
* @apiGroup JobAuditMessages
|
||||
*
|
||||
* @api {put} /api/ml/job_audit_messages/clear_messages/{jobId} Index annotation
|
||||
* @api {put} /api/ml/job_audit_messages/clear_messages Index annotation
|
||||
* @apiName ClearJobAuditMessages
|
||||
* @apiDescription Clear the job audit messages.
|
||||
*
|
||||
|
|
|
@ -77,6 +77,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
|
|||
loadTestFile(require.resolve('./filters'));
|
||||
loadTestFile(require.resolve('./indices'));
|
||||
loadTestFile(require.resolve('./job_validation'));
|
||||
loadTestFile(require.resolve('./job_audit_messages'));
|
||||
loadTestFile(require.resolve('./jobs'));
|
||||
loadTestFile(require.resolve('./modules'));
|
||||
loadTestFile(require.resolve('./results'));
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { omit } from 'lodash';
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { getJobConfig } from './index';
|
||||
import { USER } from '../../../../functional/services/ml/security_common';
|
||||
import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const ml = getService('ml');
|
||||
|
||||
let notificationIndices: string[] = [];
|
||||
|
||||
describe('clear_messages', function () {
|
||||
before(async () => {
|
||||
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote');
|
||||
await ml.testResources.setKibanaTimeZoneToUTC();
|
||||
|
||||
for (const jobConfig of getJobConfig(2)) {
|
||||
await ml.api.createAnomalyDetectionJob(jobConfig);
|
||||
}
|
||||
|
||||
const { body } = await supertest
|
||||
.get(`/api/ml/job_audit_messages/messages`)
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.expect(200);
|
||||
|
||||
notificationIndices = body.notificationIndices;
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await ml.api.cleanMlIndices();
|
||||
});
|
||||
|
||||
it('should mark audit messages as cleared for provided job', async () => {
|
||||
const timestamp = Date.now();
|
||||
|
||||
const { body } = await supertest
|
||||
.put(`/api/ml/job_audit_messages/clear_messages`)
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.send({
|
||||
jobId: 'test_get_job_audit_messages_1',
|
||||
notificationIndices,
|
||||
})
|
||||
.expect(200);
|
||||
|
||||
expect(body.success).to.eql(true);
|
||||
expect(body.last_cleared).to.be.above(timestamp);
|
||||
|
||||
const { body: getBody } = await supertest
|
||||
.get(`/api/ml/job_audit_messages/messages/test_get_job_audit_messages_1`)
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.expect(200);
|
||||
|
||||
expect(getBody.messages.length).to.eql(1);
|
||||
|
||||
expect(omit(getBody.messages[0], 'timestamp')).to.eql({
|
||||
job_id: 'test_get_job_audit_messages_1',
|
||||
message: 'Job created',
|
||||
level: 'info',
|
||||
node_name: 'node-01',
|
||||
job_type: 'anomaly_detector',
|
||||
cleared: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should not mark audit messages as cleared for the user with ML read permissions', async () => {
|
||||
const { body } = await supertest
|
||||
.put(`/api/ml/job_audit_messages/clear_messages`)
|
||||
.auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.send({
|
||||
jobId: 'test_get_job_audit_messages_2',
|
||||
notificationIndices,
|
||||
})
|
||||
.expect(403);
|
||||
expect(body.error).to.eql('Forbidden');
|
||||
expect(body.message).to.eql('Forbidden');
|
||||
|
||||
const { body: getBody } = await supertest
|
||||
.get(`/api/ml/job_audit_messages/messages/test_get_job_audit_messages_2`)
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.expect(200);
|
||||
|
||||
expect(getBody.messages[0].cleared).to.not.eql(true);
|
||||
});
|
||||
|
||||
it('should not mark audit messages as cleared for unauthorized user', async () => {
|
||||
const { body } = await supertest
|
||||
.put(`/api/ml/job_audit_messages/clear_messages`)
|
||||
.auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.send({
|
||||
jobId: 'test_get_job_audit_messages_2',
|
||||
notificationIndices,
|
||||
})
|
||||
.expect(403);
|
||||
expect(body.error).to.eql('Forbidden');
|
||||
expect(body.message).to.eql('Forbidden');
|
||||
|
||||
const { body: getBody } = await supertest
|
||||
.get(`/api/ml/job_audit_messages/messages/test_get_job_audit_messages_2`)
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.expect(200);
|
||||
|
||||
expect(getBody.messages[0].cleared).to.not.eql(true);
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { omit, keyBy } from 'lodash';
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
import { COMMON_REQUEST_HEADERS } from '../../../../functional/services/ml/common_api';
|
||||
import { USER } from '../../../../functional/services/ml/security_common';
|
||||
import { getJobConfig } from './index';
|
||||
|
||||
export default ({ getService }: FtrProviderContext) => {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const ml = getService('ml');
|
||||
|
||||
describe('get_job_audit_messages', function () {
|
||||
before(async () => {
|
||||
await esArchiver.loadIfNeeded('x-pack/test/functional/es_archives/ml/farequote');
|
||||
await ml.testResources.setKibanaTimeZoneToUTC();
|
||||
|
||||
for (const jobConfig of getJobConfig(2)) {
|
||||
await ml.api.createAnomalyDetectionJob(jobConfig);
|
||||
}
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await ml.api.cleanMlIndices();
|
||||
});
|
||||
|
||||
it('should fetch all audit messages', async () => {
|
||||
const { body } = await supertest
|
||||
.get(`/api/ml/job_audit_messages/messages`)
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.expect(200);
|
||||
|
||||
expect(body.messages.length).to.eql(2);
|
||||
|
||||
const messagesDict = keyBy(body.messages, 'job_id');
|
||||
|
||||
expect(omit(messagesDict.test_get_job_audit_messages_2, 'timestamp')).to.eql({
|
||||
job_id: 'test_get_job_audit_messages_2',
|
||||
message: 'Job created',
|
||||
level: 'info',
|
||||
node_name: 'node-01',
|
||||
job_type: 'anomaly_detector',
|
||||
});
|
||||
expect(omit(messagesDict.test_get_job_audit_messages_1, 'timestamp')).to.eql({
|
||||
job_id: 'test_get_job_audit_messages_1',
|
||||
message: 'Job created',
|
||||
level: 'info',
|
||||
node_name: 'node-01',
|
||||
job_type: 'anomaly_detector',
|
||||
});
|
||||
expect(body.notificationIndices).to.eql(['.ml-notifications-000002']);
|
||||
});
|
||||
|
||||
it('should fetch audit messages for specified job', async () => {
|
||||
const { body } = await supertest
|
||||
.get(`/api/ml/job_audit_messages/messages/test_get_job_audit_messages_1`)
|
||||
.auth(USER.ML_POWERUSER, ml.securityCommon.getPasswordForUser(USER.ML_POWERUSER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.expect(200);
|
||||
|
||||
expect(body.messages.length).to.eql(1);
|
||||
expect(omit(body.messages[0], 'timestamp')).to.eql({
|
||||
job_id: 'test_get_job_audit_messages_1',
|
||||
message: 'Job created',
|
||||
level: 'info',
|
||||
node_name: 'node-01',
|
||||
job_type: 'anomaly_detector',
|
||||
});
|
||||
expect(body.notificationIndices).to.eql(['.ml-notifications-000002']);
|
||||
});
|
||||
|
||||
it('should fetch audit messages for user with ML read permissions', async () => {
|
||||
const { body } = await supertest
|
||||
.get(`/api/ml/job_audit_messages/messages/test_get_job_audit_messages_1`)
|
||||
.auth(USER.ML_VIEWER, ml.securityCommon.getPasswordForUser(USER.ML_VIEWER))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.expect(200);
|
||||
|
||||
expect(body.messages.length).to.eql(1);
|
||||
expect(omit(body.messages[0], 'timestamp')).to.eql({
|
||||
job_id: 'test_get_job_audit_messages_1',
|
||||
message: 'Job created',
|
||||
level: 'info',
|
||||
node_name: 'node-01',
|
||||
job_type: 'anomaly_detector',
|
||||
});
|
||||
expect(body.notificationIndices).to.eql(['.ml-notifications-000002']);
|
||||
});
|
||||
|
||||
it('should not allow to fetch audit messages for unauthorized user', async () => {
|
||||
const { body } = await supertest
|
||||
.get(`/api/ml/job_audit_messages/messages/test_get_job_audit_messages_1`)
|
||||
.auth(USER.ML_UNAUTHORIZED, ml.securityCommon.getPasswordForUser(USER.ML_UNAUTHORIZED))
|
||||
.set(COMMON_REQUEST_HEADERS)
|
||||
.expect(403);
|
||||
|
||||
expect(body.error).to.eql('Forbidden');
|
||||
expect(body.message).to.eql('Forbidden');
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { MlJob } from '@elastic/elasticsearch/api/types';
|
||||
import { FtrProviderContext } from '../../../ftr_provider_context';
|
||||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('job_audit_messages', function () {
|
||||
loadTestFile(require.resolve('./get_job_audit_messages'));
|
||||
loadTestFile(require.resolve('./clear_messages'));
|
||||
});
|
||||
}
|
||||
|
||||
export const getJobConfig = (numOfJobs: number) => {
|
||||
return new Array(numOfJobs).fill(null).map(
|
||||
(v, i) =>
|
||||
(({
|
||||
job_id: `test_get_job_audit_messages_${i + 1}`,
|
||||
description: 'job_audit_messages',
|
||||
groups: ['farequote', 'automated', 'single-metric'],
|
||||
analysis_config: {
|
||||
bucket_span: '15m',
|
||||
influencers: [],
|
||||
detectors: [
|
||||
{
|
||||
function: 'mean',
|
||||
field_name: 'responsetime',
|
||||
},
|
||||
{
|
||||
function: 'min',
|
||||
field_name: 'responsetime',
|
||||
},
|
||||
],
|
||||
},
|
||||
data_description: { time_field: '@timestamp' },
|
||||
analysis_limits: { model_memory_limit: '10mb' },
|
||||
} as unknown) as MlJob)
|
||||
);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue