From 850ea25ca0f02100f3a2854026c975f1c1482d51 Mon Sep 17 00:00:00 2001 From: Christos Nasikas Date: Wed, 10 Apr 2024 11:00:55 +0300 Subject: [PATCH] Add tests for other methods --- .../methods/bulk_edit/bulk_edit_rules.test.ts | 108 ++++++++++++++++++ .../rule/methods/create/create_rule.test.ts | 4 +- .../server/rules_client/tests/update.test.ts | 37 ++++++ .../group1/tests/alerting/create.ts | 1 - .../group2/tests/alerting/update.ts | 78 ++++++++++++- .../group3/tests/alerting/bulk_edit.ts | 89 ++++++++++++++- 6 files changed, 310 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.test.ts index bc8ca1606e43e..d916a81b5fc81 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/bulk_edit/bulk_edit_rules.test.ts @@ -1581,6 +1581,114 @@ describe('bulkEdit()', () => { } `); }); + + test('should throw an error if the user does not have privileges to execute the action', async () => { + const defaultAction = { + frequency: { + notifyWhen: 'onActiveAlert' as const, + summary: false, + throttle: null, + }, + group: 'default', + id: '1', + params: {}, + }; + + const systemAction = { + id: 'system_action-id', + params: {}, + }; + + unsecuredSavedObjectsClient.bulkCreate.mockResolvedValue({ + saved_objects: [ + { + ...existingRule, + attributes: { + ...existingRule.attributes, + actions: [ + { + frequency: { + notifyWhen: 'onActiveAlert' as const, + summary: false, + throttle: null, + }, + group: 'default', + params: {}, + actionRef: 'action_0', + actionTypeId: 'test-1', + uuid: '222', + }, + { + params: {}, + actionRef: 'system_action:system_action-id', + actionTypeId: 'test-2', + uuid: '222', + }, + ], + }, + references: [ + { + name: 'action_0', + type: 'action', + id: '1', + }, + ], + }, + ], + }); + + actionsClient.getBulk.mockResolvedValue([ + { + id: '1', + actionTypeId: 'test-1', + config: {}, + isMissingSecrets: false, + name: 'test default connector', + isPreconfigured: false, + isDeprecated: false, + isSystemAction: false, + }, + { + id: 'system_action-id', + actionTypeId: 'test-2', + config: {}, + isMissingSecrets: false, + name: 'system action connector', + isPreconfigured: false, + isDeprecated: false, + isSystemAction: true, + }, + ]); + + actionsAuthorization.ensureAuthorized.mockRejectedValueOnce( + new Error('Unauthorized to execute actions') + ); + + const res = await rulesClient.bulkEdit({ + filter: '', + operations: [ + { + field: 'actions', + operation: 'add', + value: [defaultAction, systemAction], + }, + ], + }); + + expect(res.rules.length).toBe(0); + expect(res.skipped.length).toBe(0); + expect(res.total).toBe(1); + + expect(res.errors).toEqual([ + { + message: 'Unauthorized to execute actions', + rule: { + id: '1', + name: 'my rule name', + }, + }, + ]); + }); }); describe('index pattern operations', () => { diff --git a/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.test.ts b/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.test.ts index 83483d09fc33e..50f5abb5d3d73 100644 --- a/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.test.ts +++ b/x-pack/plugins/alerting/server/application/rule/methods/create/create_rule.test.ts @@ -4356,7 +4356,7 @@ describe('create()', () => { test('should throw an error if the user does not have privileges to execute the action', async () => { actionsAuthorization.ensureAuthorized.mockRejectedValueOnce( - 'Unauthorized to execute actions' + new Error('Unauthorized to execute actions') ); const data = getMockData({ @@ -4380,7 +4380,7 @@ describe('create()', () => { }); await expect(() => rulesClient.create({ data })).rejects.toMatchInlineSnapshot( - `"Unauthorized to execute actions"` + `[Error: Unauthorized to execute actions]` ); }); }); diff --git a/x-pack/plugins/alerting/server/rules_client/tests/update.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/update.test.ts index d66b17b5ff6b6..4daf489091d2c 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/update.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/update.test.ts @@ -3837,5 +3837,42 @@ describe('update()', () => { `[Error: Error validating actions - [actions.0.group]: expected value of type [string] but got [undefined]]` ); }); + + test('should throw an error if the user does not have privileges to execute the action', async () => { + actionsAuthorization.ensureAuthorized.mockRejectedValueOnce( + new Error('Unauthorized to execute actions') + ); + + await expect(() => + rulesClient.update({ + id: '1', + data: { + schedule: { interval: '1m' }, + name: 'abc', + tags: ['foo'], + params: { + bar: true, + }, + throttle: null, + notifyWhen: 'onActiveAlert', + actions: [ + { + group: 'default', + id: '1', + params: { + foo: true, + }, + }, + ], + systemActions: [ + { + id: 'system_action-id', + params: {}, + }, + ], + }, + }) + ).rejects.toMatchInlineSnapshot(`[Error: Unauthorized to execute actions]`); + }); }); }); diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts index 6f3227c552118..10359b53f0355 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group1/tests/alerting/create.ts @@ -582,7 +582,6 @@ export default function createAlertTests({ getService }: FtrProviderContext) { statusCode: 403, }); break; - case 'space_1_all_alerts_none_actions at space1': expect(response.statusCode).to.eql(403); expect(response.body).to.eql({ diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts index 3771039e392c9..34388914b10ff 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/alerting/update.ts @@ -11,7 +11,8 @@ import { RuleNotifyWhen, RULE_SAVED_OBJECT_TYPE } from '@kbn/alerting-plugin/ser import { RawRule } from '@kbn/alerting-plugin/server/types'; import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { SavedObject } from '@kbn/core-saved-objects-api-server'; -import { SuperuserAtSpace1, UserAtSpaceScenarios } from '../../../scenarios'; +import { ES_TEST_INDEX_NAME } from '@kbn/alerting-api-integration-helpers'; +import { SuperuserAtSpace1, systemActionScenario, UserAtSpaceScenarios } from '../../../scenarios'; import { checkAAD, getUrlPrefix, @@ -41,7 +42,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { after(() => objectRemover.removeAll()); - for (const scenario of UserAtSpaceScenarios) { + for (const scenario of [...UserAtSpaceScenarios, systemActionScenario]) { const { user, space } = scenario; describe(scenario.id, () => { it('should handle update alert request appropriately', async () => { @@ -994,6 +995,79 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); } }); + + it('should handle create alert request appropriately with system actions', async () => { + const connectorId = 'system-connector-test.system-action-kibana-privileges'; + const reference = `actions-enqueue-${scenario.id}:${space.id}:${connectorId}`; + + const systemActionWithKibanaPrivileges = { + id: connectorId, + group: 'default', + params: { index: ES_TEST_INDEX_NAME, reference }, + }; + + const { body: createdAlert } = await supertest + .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData()) + .expect(200); + + objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); + + const updatedData = { + name: 'bcd', + tags: ['bar'], + params: { + foo: true, + }, + schedule: { interval: '12s' }, + actions: [systemActionWithKibanaPrivileges], + throttle: '1m', + notify_when: 'onThrottleInterval', + }; + + const response = await supertestWithoutAuth + .put(`${getUrlPrefix(space.id)}/api/alerting/rule/${createdAlert.id}`) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password) + .send(updatedData); + + switch (scenario.id) { + case 'no_kibana_privileges at space1': + case 'global_read at space1': + case 'space_1_all at space2': + expect(response.statusCode).to.eql(403); + expect(response.body).to.eql({ + error: 'Forbidden', + message: getUnauthorizedErrorMessage('update', 'test.noop', 'alertsFixture'), + statusCode: 403, + }); + break; + case 'space_1_all at space1': + case 'space_1_all_with_restricted_fixture at space1': + expect(response.statusCode).to.eql(403); + expect(response.body).to.eql({ + error: 'Forbidden', + message: 'Unauthorized to execute actions', + statusCode: 403, + }); + break; + case 'space_1_all_alerts_none_actions at space1': + expect(response.statusCode).to.eql(403); + expect(response.body).to.eql({ + error: 'Forbidden', + message: `Unauthorized to get actions`, + statusCode: 403, + }); + break; + case 'superuser at space1': + case 'system_actions at space1': + expect(response.statusCode).to.eql(200); + break; + default: + throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); + } + }); }); } diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts index f09ab4b2fe66d..48ca8ac88f102 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts @@ -11,7 +11,8 @@ import { RuleNotifyWhen, SanitizedRule } from '@kbn/alerting-plugin/common'; import { RULE_SAVED_OBJECT_TYPE } from '@kbn/alerting-plugin/server'; import { RawRule } from '@kbn/alerting-plugin/server/types'; import { ALERTING_CASES_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; -import { SuperuserAtSpace1, UserAtSpaceScenarios } from '../../../scenarios'; +import { ES_TEST_INDEX_NAME } from '@kbn/alerting-api-integration-helpers'; +import { SuperuserAtSpace1, systemActionScenario, UserAtSpaceScenarios } from '../../../scenarios'; import { checkAAD, getUrlPrefix, @@ -32,7 +33,7 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { after(() => objectRemover.removeAll()); - for (const scenario of UserAtSpaceScenarios) { + for (const scenario of [...UserAtSpaceScenarios, systemActionScenario]) { const { user, space } = scenario; describe(scenario.id, () => { it('should handle bulk edit of rules appropriately', async () => { @@ -601,6 +602,90 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); } }); + + it('should handle bulk edit rules with system actions', async () => { + const connectorId = 'system-connector-test.system-action-kibana-privileges'; + const reference = `actions-enqueue-${scenario.id}:${space.id}:${connectorId}`; + + const { body: createdRule } = await supertest + .post(`${getUrlPrefix(space.id)}/api/alerting/rule`) + .set('kbn-xsrf', 'foo') + .send(getTestRuleData()) + .expect(200); + + objectRemover.add(space.id, createdRule.id, 'rule', 'alerting'); + + const response = await supertestWithoutAuth + .post(`${getUrlPrefix(space.id)}/internal/alerting/rules/_bulk_edit`) + .set('kbn-xsrf', 'foo') + .auth(user.username, user.password) + .send({ + ids: [createdRule.id], + operations: [ + { + operation: 'add', + field: 'actions', + value: [ + { + id: connectorId, + params: { index: ES_TEST_INDEX_NAME, reference }, + }, + ], + }, + ], + }); + + 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: 'Unauthorized to find rules for any rule types', + statusCode: 403, + }); + + break; + case 'global_read at space1': + expect(response.statusCode).to.eql(403); + expect(response.body).to.eql({ + error: 'Forbidden', + message: getUnauthorizedErrorMessage('bulkEdit', 'test.noop', 'alertsFixture'), + statusCode: 403, + }); + + break; + case 'space_1_all at space1': + case 'space_1_all_with_restricted_fixture at space1': + expect(response.statusCode).to.eql(200); + expect(response.body.errors).to.eql([ + { + message: 'Unauthorized to execute actions', + rule: { id: createdRule.id, name: createdRule.name }, + }, + ]); + + break; + case 'space_1_all_alerts_none_actions at space1': + expect(response.statusCode).to.eql(200); + expect(response.body.errors).to.eql([ + { + message: 'Unauthorized to get actions', + rule: { id: createdRule.id, name: createdRule.name }, + }, + ]); + + break; + case 'superuser at space1': + case 'system_actions at space1': + expect(response.statusCode).to.eql(200); + expect(response.body.errors).to.eql([]); + + break; + default: + throw new Error(`Scenario untested: ${JSON.stringify(scenario)}`); + } + }); }); }