-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[Security Solution] Prevent same rule from being imported concurrently #180519
base: main
Are you sure you want to change the base?
Changes from all commits
3158cd6
4dd06cc
ec172f7
c12bfbd
fe925cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,6 +20,8 @@ import { createBulkErrorObject } from '../../../routes/utils'; | |
import { createRules } from '../crud/create_rules'; | ||
import { readRules } from '../crud/read_rules'; | ||
import { updateRules } from '../crud/update_rules'; | ||
import { deleteRules } from '../crud/delete_rules'; | ||
import { findRules } from '../search/find_rules'; | ||
import type { MlAuthz } from '../../../../machine_learning/authz'; | ||
import { throwAuthzError } from '../../../../machine_learning/validation'; | ||
import { checkRuleExceptionReferences } from './check_rule_exception_references'; | ||
|
@@ -104,18 +106,41 @@ export const importRules = async ({ | |
}); | ||
|
||
if (rule == null) { | ||
await createRules({ | ||
const createdRule = await createRules({ | ||
rulesClient, | ||
params: { | ||
...parsedRule, | ||
exceptions_list: [...exceptions], | ||
}, | ||
allowMissingConnectorSecrets, | ||
}); | ||
resolve({ | ||
rule_id: parsedRule.rule_id, | ||
status_code: 200, | ||
// find rules with the same rule_id, in case of concurrent imports | ||
const rules = await findRules({ | ||
rulesClient, | ||
filter: `alert.attributes.params.ruleId: "${parsedRule.rule_id}"`, | ||
page: 1, | ||
fields: undefined, | ||
perPage: undefined, | ||
sortField: 'created_at', | ||
sortOrder: 'asc', | ||
}); | ||
// OK if it is a unique rule or the earlier rule created | ||
if (rules.total === 1 || createdRule.id === rules.data[0].id) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The second condition AND condition would work though
|
||
resolve({ | ||
rule_id: parsedRule.rule_id, | ||
status_code: 200, | ||
}); | ||
// else delete the duplicate rule and return status 409 | ||
} else { | ||
deleteRules({ ruleId: createdRule.id, rulesClient }); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
resolve( | ||
createBulkErrorObject({ | ||
ruleId: parsedRule.rule_id, | ||
statusCode: 409, | ||
message: `rule_id: "${parsedRule.rule_id}" already exists`, | ||
}) | ||
); | ||
} | ||
} else if (rule != null && overwriteRules) { | ||
await updateRules({ | ||
rulesClient, | ||
|
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.
In rare cases two (or more) rules with the same ruleId can be created in parallel so
findRules()
would return two rules which will lead to both of them deleted.