mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
[RAM] Add missing privilege to alerting read operations (#166603)
Closes #158957
## Summary
Adds the missing `getActionErrorLog` privilege. With the updated
privileges, users with a custom Role including full access to "Actions
and Connectors", "Rule Settings" and "Stack Rules" can successfully
inspect errored actions' logs:

## To Test
- Create a Role with `All` privileges granted in `Actions and
Connectors`, `Rules Settings`, `Stack Rules` (under Kibana > Management)
and assign it to a user
- Log in with that user
- Create a rule with a failing action (i.e. an Email Connector with
wrong addresses)
- Wait for the rule to execute (or execute it manually)
- In the rule page, under `History` click the number under `Errored
actions` in one of the rows of the logs table
- Check that error logs are visible in the flyout
This commit is contained in:
parent
416dabf505
commit
0eda41a46d
3 changed files with 113 additions and 4 deletions
|
@ -87,6 +87,7 @@ describe(`feature_privilege_builder`, () => {
|
|||
"alerting:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:alert-type/my-feature/rule/getExecutionLog",
|
||||
"alerting:alert-type/my-feature/rule/getActionErrorLog",
|
||||
"alerting:alert-type/my-feature/rule/find",
|
||||
"alerting:alert-type/my-feature/rule/getRuleExecutionKPI",
|
||||
"alerting:alert-type/my-feature/rule/runSoon",
|
||||
|
@ -174,6 +175,7 @@ describe(`feature_privilege_builder`, () => {
|
|||
"alerting:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:alert-type/my-feature/rule/getExecutionLog",
|
||||
"alerting:alert-type/my-feature/rule/getActionErrorLog",
|
||||
"alerting:alert-type/my-feature/rule/find",
|
||||
"alerting:alert-type/my-feature/rule/getRuleExecutionKPI",
|
||||
"alerting:alert-type/my-feature/rule/runSoon",
|
||||
|
@ -221,6 +223,7 @@ describe(`feature_privilege_builder`, () => {
|
|||
"alerting:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:alert-type/my-feature/rule/getExecutionLog",
|
||||
"alerting:alert-type/my-feature/rule/getActionErrorLog",
|
||||
"alerting:alert-type/my-feature/rule/find",
|
||||
"alerting:alert-type/my-feature/rule/getRuleExecutionKPI",
|
||||
"alerting:alert-type/my-feature/rule/runSoon",
|
||||
|
@ -325,6 +328,7 @@ describe(`feature_privilege_builder`, () => {
|
|||
"alerting:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:alert-type/my-feature/rule/getExecutionLog",
|
||||
"alerting:alert-type/my-feature/rule/getActionErrorLog",
|
||||
"alerting:alert-type/my-feature/rule/find",
|
||||
"alerting:alert-type/my-feature/rule/getRuleExecutionKPI",
|
||||
"alerting:alert-type/my-feature/rule/runSoon",
|
||||
|
@ -389,6 +393,7 @@ describe(`feature_privilege_builder`, () => {
|
|||
"alerting:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:alert-type/my-feature/rule/getExecutionLog",
|
||||
"alerting:alert-type/my-feature/rule/getActionErrorLog",
|
||||
"alerting:alert-type/my-feature/rule/find",
|
||||
"alerting:alert-type/my-feature/rule/getRuleExecutionKPI",
|
||||
"alerting:alert-type/my-feature/rule/runSoon",
|
||||
|
@ -412,6 +417,7 @@ describe(`feature_privilege_builder`, () => {
|
|||
"alerting:readonly-alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:readonly-alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:readonly-alert-type/my-feature/rule/getExecutionLog",
|
||||
"alerting:readonly-alert-type/my-feature/rule/getActionErrorLog",
|
||||
"alerting:readonly-alert-type/my-feature/rule/find",
|
||||
"alerting:readonly-alert-type/my-feature/rule/getRuleExecutionKPI",
|
||||
"alerting:readonly-alert-type/my-feature/rule/runSoon",
|
||||
|
@ -504,6 +510,7 @@ describe(`feature_privilege_builder`, () => {
|
|||
"alerting:alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:alert-type/my-feature/rule/getExecutionLog",
|
||||
"alerting:alert-type/my-feature/rule/getActionErrorLog",
|
||||
"alerting:alert-type/my-feature/rule/find",
|
||||
"alerting:alert-type/my-feature/rule/getRuleExecutionKPI",
|
||||
"alerting:alert-type/my-feature/rule/runSoon",
|
||||
|
@ -527,6 +534,7 @@ describe(`feature_privilege_builder`, () => {
|
|||
"alerting:readonly-alert-type/my-feature/rule/getRuleState",
|
||||
"alerting:readonly-alert-type/my-feature/rule/getAlertSummary",
|
||||
"alerting:readonly-alert-type/my-feature/rule/getExecutionLog",
|
||||
"alerting:readonly-alert-type/my-feature/rule/getActionErrorLog",
|
||||
"alerting:readonly-alert-type/my-feature/rule/find",
|
||||
"alerting:readonly-alert-type/my-feature/rule/getRuleExecutionKPI",
|
||||
"alerting:readonly-alert-type/my-feature/rule/runSoon",
|
||||
|
|
|
@ -22,6 +22,7 @@ const readOperations: Record<AlertingEntity, string[]> = {
|
|||
'getRuleState',
|
||||
'getAlertSummary',
|
||||
'getExecutionLog',
|
||||
'getActionErrorLog',
|
||||
'find',
|
||||
'getRuleExecutionKPI',
|
||||
'runSoon',
|
||||
|
|
|
@ -8,13 +8,20 @@
|
|||
import expect from '@kbn/expect';
|
||||
|
||||
import { ESTestIndexTool } from '@kbn/alerting-api-integration-helpers';
|
||||
import { Spaces } from '../../../scenarios';
|
||||
import { getUrlPrefix, ObjectRemover, getTestRuleData, getEventLog } from '../../../../common/lib';
|
||||
import { Spaces, UserAtSpaceScenarios } from '../../../scenarios';
|
||||
import {
|
||||
getUrlPrefix,
|
||||
ObjectRemover,
|
||||
getTestRuleData,
|
||||
getEventLog,
|
||||
getConsumerUnauthorizedErrorMessage,
|
||||
} from '../../../../common/lib';
|
||||
import { FtrProviderContext } from '../../../../common/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function createGetActionErrorLogTests({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const supertestWithoutAuth = getService('supertestWithoutAuth');
|
||||
const retry = getService('retry');
|
||||
const es = getService('es');
|
||||
const esTestIndexTool = new ESTestIndexTool(es, retry);
|
||||
|
@ -33,6 +40,98 @@ export default function createGetActionErrorLogTests({ getService }: FtrProvider
|
|||
await objectRemover.removeAll();
|
||||
});
|
||||
|
||||
for (const scenario of UserAtSpaceScenarios) {
|
||||
const { user, space } = scenario;
|
||||
describe(scenario.id, () => {
|
||||
it('gets action error logs for rules with action errors with appropriate authorization', async () => {
|
||||
const { body: createdConnector } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/actions/connector`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({
|
||||
name: 'connector that throws',
|
||||
connector_type_id: 'test.throw',
|
||||
config: {},
|
||||
secrets: {},
|
||||
})
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdConnector.id, 'action', 'actions');
|
||||
|
||||
const { body: createdRule } = await supertest
|
||||
.post(`${getUrlPrefix(space.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(
|
||||
getTestRuleData({
|
||||
rule_type_id: 'test.cumulative-firing',
|
||||
actions: [
|
||||
{
|
||||
id: createdConnector.id,
|
||||
group: 'default',
|
||||
params: {},
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
.expect(200);
|
||||
objectRemover.add(space.id, createdRule.id, 'rule', 'alerting');
|
||||
|
||||
await waitForEvents(
|
||||
createdRule.id,
|
||||
'alerting',
|
||||
new Map([['execute', { gte: 1 }]]),
|
||||
space.id
|
||||
);
|
||||
await waitForEvents(
|
||||
createdRule.id,
|
||||
'actions',
|
||||
new Map([['execute', { gte: 1 }]]),
|
||||
space.id
|
||||
);
|
||||
|
||||
const response = await supertestWithoutAuth
|
||||
.get(
|
||||
`${getUrlPrefix(space.id)}/internal/alerting/rule/${
|
||||
createdRule.id
|
||||
}/_action_error_log?date_start=${dateStart}`
|
||||
)
|
||||
.auth(user.username, user.password);
|
||||
|
||||
switch (scenario.id) {
|
||||
case 'no_kibana_privileges at space1':
|
||||
case 'space_1_all at space2':
|
||||
expect(response.statusCode).to.eql(403);
|
||||
expect(response.body).to.eql({
|
||||
error: 'Forbidden',
|
||||
message: getConsumerUnauthorizedErrorMessage(
|
||||
'get',
|
||||
'test.cumulative-firing',
|
||||
'alertsFixture'
|
||||
),
|
||||
statusCode: 403,
|
||||
});
|
||||
break;
|
||||
case 'global_read at space1':
|
||||
case 'superuser at space1':
|
||||
case 'space_1_all at space1':
|
||||
case 'space_1_all_alerts_none_actions at space1':
|
||||
case 'space_1_all_with_restricted_fixture at space1':
|
||||
expect(response.statusCode).to.eql(200);
|
||||
expect(response.body.totalErrors).to.eql(1);
|
||||
expect(response.body.errors.length).to.eql(1);
|
||||
|
||||
for (const errors of response.body.errors) {
|
||||
expect(errors.type).to.equal('actions');
|
||||
expect(errors.message).to.equal(
|
||||
`action execution failure: test.throw:${createdConnector.id}: connector that throws - an error occurred while running the action: this action is intended to fail; retry: true`
|
||||
);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('gets action error logs from an alternate space', async () => {
|
||||
const { body: createdConnector } = await supertest
|
||||
.post(`${getUrlPrefix(Spaces[1].id)}/api/actions/connector`)
|
||||
|
@ -99,12 +198,13 @@ export default function createGetActionErrorLogTests({ getService }: FtrProvider
|
|||
{
|
||||
gte: number;
|
||||
}
|
||||
>
|
||||
>,
|
||||
spaceId = Spaces[1].id
|
||||
) {
|
||||
await retry.try(async () => {
|
||||
return await getEventLog({
|
||||
getService,
|
||||
spaceId: Spaces[1].id,
|
||||
spaceId,
|
||||
type: 'alert',
|
||||
id,
|
||||
provider,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue