-
Notifications
You must be signed in to change notification settings - Fork 8.4k
[ResponseOps][Rules] Prevent internally managed rule types to be disabled/enabled from the APIs #236672
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Pinging @elastic/response-ops (Team:ResponseOps) |
@elasticmachine merge upstream |
💔 Build Failed
Failed CI StepsTest Failures
Metrics [docs]
History
cc @cnasikas |
import { rulesClientMock } from '../../mocks'; | ||
import { validateInternalRuleTypesByQuery } from './validate_internal_rule_types_by_query'; | ||
|
||
describe('validateInternalRuleTypesByQuery', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: missing happy path test.
}); | ||
|
||
describe('internally managed rule types', () => { | ||
it('throws 400 if the rule type is internally managed', async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reading these for the different APIs, I noticed you don't test the "Rule type not found"
error path. I think it is fine, but I just wanna confirm. For each of these routes, the rulesClient
does that check too, right?
import type { RegistryRuleType } from '../../rule_type_registry'; | ||
import type { RulesClient } from '../../rules_client'; | ||
|
||
export const validateInternalRuleTypesByQuery = async ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like we had this conversation, but I don't remember the outcome 😅
I agree that the check should be done at the route level, but why is this function not defined in the rules client itself?
The routes would then do
rulesClient.validateInternalRuleTypesByQuery({
req: body,
ruleTypes,
operationText: 'disable',
})
const bulkDisableResults = await rulesClient.bulkDisableRules({ filter, ids, untrack });
Or something like that.
const disableParams = { id, untrack }; | ||
|
||
try { | ||
const rule = await rulesClient.get({ id }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why don't these(disable+enable) use validateInternalRuleTypesByQuery
? Is it because of getRuleTypesByQuery
? The performance should be fine if filter
is optional and only an id
is passed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The validateInternalRuleTypesByQuery
does an ES aggregation to see if the rule is internal. I find it simpler to reason, explicit, and more performant if we do a single check. Also, if in the future the validateInternalRuleTypesByQuery
changes to a way that supports only bulk edits, we will not have to go to all single routes and change the logic.
|
||
it('should throw 400 error when trying to update an internally managed rule type', async () => { | ||
const { body: createdRule1 } = await supertest | ||
const { body: createdRule } = await supertest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test is for update
but the change was done to bulk_edit_rules_route
. Should a test also be added to x-pack/platform/test/alerting_api_integration/security_and_spaces/group3/tests/alerting/bulk_edit.ts
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests for the bulk_edit
and update
were introduced in this #234937. Here, I fixed a bug in the test, I realized.
const ruleTypesByQuery = await rulesClient.getRuleTypesByQuery({ filter, ids }); | ||
const ruleTypeIds = new Set(ruleTypesByQuery.ruleTypes); | ||
|
||
for (const ruleTypeId of ruleTypeIds) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this validation is for bulk operations, maybe we should add the errors to an array and only throw at the end with all the failing rules? wdyt?
I say "maybe" because if the user sets the filter
option, it isn't very helpful.
However, in a scenario where multiple IDs are passed, if we throw the first one, the user removes it from the list, and then the API throws again, and again. It is not great UX.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is not possible with the filter
option to do it, but I would give it a try for the ids
.
const ruleType = ruleTypes.get(ruleTypeId); | ||
|
||
if (!ruleType) { | ||
throw Boom.badRequest('Rule type not found'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could include the rule type id here, should help to debug if needed
} | ||
|
||
if (ruleType.internallyManaged) { | ||
throw Boom.badRequest( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no time to test it, so I might be wrong here. But if we call a bulk action, let's say for all rules. What exactly happens here? For me it looks like, if there is an internal rule type, it will throw, not being able to run that bulk action on the other rules (those belonging to non internally managed types). This would make the whole bulk action useless as soon as there is an internally managed rule type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is correct, and it is the intended behavior. It is much better to fail early for all than to introduce side effects where some of them are updated and some are not. Aside from the complexity of handling the various cases, the route should be idempotent on every call and failing early, regardless of achieving that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't we ignore internally managed rules by filtering them out? That should keep it idempotent. We don't have to throw an error once we get to internally managed rule type. It's also worsening UX: users with internally managed rules won't be able to bulk edit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An API should be clear on its behavior. Filtering out internal rule types would confuse users because it is not clear why they are not updated (the API returned 200). I get the UX issue, which I agree with, but I think this should be addressed on the UI level. Btw, all prior validations work like this. If one of the rules fails to pass a condition, the whole API throws.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will open an issue for the UX/UI. We need to make it clear that the rule is internally managed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested and works as expected 👍
Summary
This PR prevents internally managed rule types from being enabled/disabled through the Rule Disable, Enable and Bulk Enable and Disable APIs. The prevention logic is on he route level because we want to support updating internally managed rules from the alerts client.
Partial fixes: #222101
Checklist
Check the PR satisfies following conditions.
Reviewers should verify this PR satisfies this list as well.