Skip to content
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] RFC for Prebuilt Rules Customization - Milestone 3 #171856

Merged
merged 62 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
c0f2e05
RFC for Prebuilt Rules Customization - Phase 3 - Part 1
jpdjere Nov 23, 2023
053ecd6
Refactor: Updated schema definitions
jpdjere Feb 13, 2024
308709d
Refactor: Updated migration context
jpdjere Feb 13, 2024
b95a529
Refactor: Normalization on write
jpdjere Feb 13, 2024
a461cf5
Refactor: Add table for updating actions
jpdjere Feb 13, 2024
a29bea1
Refactor: removed code implementation details for update migrations
jpdjere Feb 13, 2024
5c72739
Refactor: Added Bulk editing rules section
jpdjere Feb 13, 2024
499dc4c
Refactor: KQL filters and the method section
jpdjere Feb 13, 2024
2265ba1
Refactor: Clean up endpoint modifications
jpdjere Feb 14, 2024
0647a4f
Refactor: Add section
jpdjere Feb 14, 2024
15795cb
Refactor: Further simplified endpoints
jpdjere Feb 14, 2024
eab1c4b
Refactor: Deleted importing cases table
jpdjere Feb 15, 2024
6363547
Refactor: Minor fix
jpdjere Feb 15, 2024
26c7fad
Refactor: Started rewriting based on rule_source_type and import feed…
jpdjere Feb 19, 2024
f2f5ffb
Refactor: Modified migration table and KQL filters to account for rul…
jpdjere Feb 19, 2024
e0ec4e0
Refactor: Started rewriting import logic
jpdjere Feb 19, 2024
28f5380
Refactor: Rewrote all sections to account for 'rule_source'
jpdjere Feb 21, 2024
6b6578a
Part 2: Started concrete diffs implementation
jpdjere Feb 21, 2024
89fe78a
Part 2: Add algorithm use cases
jpdjere Feb 22, 2024
275c36d
Part 2: Add algorithm for solving array changes
jpdjere Feb 22, 2024
440ac2a
Part 2: Typo
jpdjere Feb 22, 2024
5842ce7
Part 2: Merged array of strings and objects algorithms
jpdjere Feb 23, 2024
794d3bb
Part 2: Added changes to upgrade /_review and /_perform endpoints
jpdjere Feb 23, 2024
283c706
Part 2: Remove changes for endpoints and link to POC
jpdjere Feb 23, 2024
2ed015e
Part 2: cleanup
jpdjere Feb 25, 2024
3aa1ac5
Removed line
jpdjere Mar 4, 2024
08ac332
Rework status
jpdjere Mar 4, 2024
c7418a2
Add ToC
jpdjere Mar 4, 2024
9a18e16
Added pending changes
jpdjere Mar 12, 2024
f27c13d
Update status
jpdjere Mar 18, 2024
30fc99f
Addressing feedback
jpdjere Mar 18, 2024
2e0cd26
Addressing feedback
jpdjere Mar 18, 2024
184eb02
Addressing feedback
jpdjere Mar 18, 2024
c073689
Addressing feedback
jpdjere Mar 18, 2024
e722c10
Addressing feedback
jpdjere Mar 18, 2024
072d009
Addressing feedback
jpdjere Mar 18, 2024
9481602
Addressing feedback
jpdjere Mar 18, 2024
c0da34f
Added table for migration type
jpdjere Mar 18, 2024
582bd8e
Addressing feedback
jpdjere Mar 18, 2024
ac6ac12
Addressing feedback
jpdjere Mar 18, 2024
08c945e
Addressing feedback
jpdjere Mar 18, 2024
826c239
Addressing feedback
jpdjere Mar 18, 2024
d92ebd6
Started fixing concrete diff algorithms section
jpdjere Mar 22, 2024
5ef3901
Fix Numbers algorithm
jpdjere Mar 22, 2024
d38964c
Change
jpdjere Mar 22, 2024
f797266
Add explanation
jpdjere Mar 22, 2024
e44c570
Added references to nodeDiff3
jpdjere Mar 22, 2024
820034e
Cleanup
jpdjere Mar 22, 2024
473c1dc
Fixed Array of strings section
jpdjere Mar 25, 2024
c1e97d5
Fix
jpdjere Mar 25, 2024
01ed741
Fixed 'Array of objects' section
jpdjere Mar 25, 2024
c3c9e7e
Finished correction
jpdjere Mar 25, 2024
bc14d24
Fix TOC
jpdjere Mar 26, 2024
484f977
Address further feedback
jpdjere Mar 27, 2024
8da0a9d
Further fix
jpdjere Mar 27, 2024
e710787
Address feedback
jpdjere Apr 1, 2024
30ac113
Addressed final feedback round
jpdjere Apr 2, 2024
ee72802
Removed test changes
jpdjere Apr 3, 2024
74d4f8d
Other changes reverted
jpdjere Apr 3, 2024
924e393
Add CODEOWNERS
jpdjere Apr 3, 2024
dadbd7d
Merge branch 'main' into rfc-prebuilt-rules-customization
jpdjere Apr 3, 2024
bc67346
Fixes
jpdjere Apr 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ import {
transformRuleDomainToRule,
} from '../../transforms';
import { validateScheduleLimit, ValidateScheduleLimitResult } from '../get_schedule_frequency';
import { migratePrebuiltSchemaOnRuleBulkEdit } from './schemas/migrate_prebuilt_schema_on_bulk_edit';

const isValidInterval = (interval: string | undefined): interval is string => {
return interval !== undefined;
Expand Down Expand Up @@ -512,9 +513,13 @@ async function updateRuleAttributesAndParamsInMemory<Params extends RuleParams>(
updatedRule.revision += 1;
}

const isRuleUpdated = !(isAttributesUpdateSkipped && isParamsUpdateSkipped);

migratePrebuiltSchemaOnRuleBulkEdit(ruleParams, isRuleUpdated);

// If neither attributes nor parameters were updated, mark
// the rule as skipped and continue to the next rule.
if (isAttributesUpdateSkipped && isParamsUpdateSkipped) {
if (!isRuleUpdated) {
skipped.push({
id: rule.id,
name: rule.attributes.name,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* 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 { RuleParams } from '../../../types';

const getPrebuiltValueForRuleBulkEdit = (
ruleParams: RuleParams,
isRuleUpdatedDuringBulkUpdate: boolean
) => {
if (ruleParams?.prebuilt) {
return {
...ruleParams.prebuilt,
isCustomized: ruleParams.prebuilt.isCustomized || isRuleUpdatedDuringBulkUpdate,
};
}

if (ruleParams.immutable) {
return {
isCustomized: isRuleUpdatedDuringBulkUpdate,
};
}

return undefined;
};

export const migratePrebuiltSchemaOnRuleBulkEdit = (
ruleParams: RuleParams,
isRuleUpdatedDuringBulkUpdate: boolean
) => {
const immutable = Boolean(ruleParams.prebuilt) || ruleParams.immutable;
const prebuilt = getPrebuiltValueForRuleBulkEdit(ruleParams, isRuleUpdatedDuringBulkUpdate);

ruleParams.prebuilt = prebuilt;
ruleParams.immutable = immutable;
};
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,33 @@ export const KqlQueryLanguage = z.enum(['kuery', 'lucene']);
export type KqlQueryLanguageEnum = typeof KqlQueryLanguage.enum;
export const KqlQueryLanguageEnum = KqlQueryLanguage.enum;

/**
* [DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).
*/
export type IsRuleImmutable = z.infer<typeof IsRuleImmutable>;
export const IsRuleImmutable = z.boolean();

/**
* Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value).
*/
export type IsPrebuiltRuleCustomized = z.infer<typeof IsPrebuiltRuleCustomized>;
export const IsPrebuiltRuleCustomized = z.boolean();

/**
* The date and time that the prebuilt rule was last updated by Elastic.
*/
export type ElasticUpdateDate = z.infer<typeof ElasticUpdateDate>;
export const ElasticUpdateDate = z.string().datetime();

/**
* Property whose existence determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules.
*/
export type Prebuilt = z.infer<typeof Prebuilt>;
export const Prebuilt = z.object({
isCustomized: IsPrebuiltRuleCustomized,
elasticUpdateDate: ElasticUpdateDate.optional(),
});

/**
* Determines whether the rule is enabled.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,27 @@ components:

IsRuleImmutable:
type: boolean
description: '[DEPRECATION WARNING - This field is deprecated and will be removed in a future release. Use the prebuilt field to determine if a rule is an Elastic prebuilt rule or a custom rule.] - Determines whether the rule is immutable (i.e. cannot be modified by the user).'

IsPrebuiltRuleCustomized:
type: boolean
description: Determines whether the prebuilt rule has been customized by the user (i.e. any of its fields have been modified and diverge from the base value).

ElasticUpdateDate:
type: string
format: date-time
description: The date and time that the prebuilt rule was last updated by Elastic.

Prebuilt:
type: object
description: Property whose existence determines whether the rule is an Elastic Prebuilt Rule that can receive upstream updates via Fleet. Contains information relating to prebuilt rules.
properties:
isCustomized:
$ref: '#/components/schemas/IsPrebuiltRuleCustomized'
elasticUpdateDate:
$ref: '#/components/schemas/ElasticUpdateDate'
required:
- isCustomized

IsRuleEnabled:
type: boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
RuleObjectId,
RuleSignatureId,
IsRuleImmutable,
Prebuilt,
RelatedIntegrationArray,
RequiredFieldArray,
SetupGuide,
Expand Down Expand Up @@ -155,6 +156,7 @@ export const ResponseFields = z.object({
id: RuleObjectId,
rule_id: RuleSignatureId,
immutable: IsRuleImmutable,
prebuilt: Prebuilt.optional(),
updated_at: z.string().datetime(),
updated_by: z.string(),
created_at: z.string().datetime(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ components:
$ref: './common_attributes.schema.yaml#/components/schemas/RuleSignatureId'
immutable:
$ref: './common_attributes.schema.yaml#/components/schemas/IsRuleImmutable'
prebuilt:
$ref: './common_attributes.schema.yaml#/components/schemas/Prebuilt'
updated_at:
type: string
format: date-time
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
* 2.0.
*/

import * as z from 'zod';
import type * as z from 'zod';
import {
BaseCreateProps,
ResponseFields,
RuleSignatureId,
TypeSpecificCreateProps,
IsRuleImmutable,
Prebuilt,
} from '../../model/rule_schema';

/**
Expand All @@ -28,6 +30,7 @@ export type RuleToImportInput = z.input<typeof RuleToImport>;
export const RuleToImport = BaseCreateProps.and(TypeSpecificCreateProps).and(
ResponseFields.partial().extend({
rule_id: RuleSignatureId,
immutable: z.literal(false).default(false),
immutable: IsRuleImmutable.optional(),
prebuilt: Prebuilt.optional(),
})
);
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,6 @@ export const ENABLED_FIELD = 'alert.attributes.enabled';
export const TAGS_FIELD = 'alert.attributes.tags';
export const PARAMS_TYPE_FIELD = 'alert.attributes.params.type';
export const PARAMS_IMMUTABLE_FIELD = 'alert.attributes.params.immutable';
export const PARAMS_PREBUILT_FIELD = 'alert.attributes.params.prebuilt';
export const PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD = 'alert.attributes.params.prebuilt.isCustomized';
export const LAST_RUN_OUTCOME_FIELD = 'alert.attributes.lastRun.outcome';
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ import {
ENABLED_FIELD,
LAST_RUN_OUTCOME_FIELD,
PARAMS_IMMUTABLE_FIELD,
PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD,
PARAMS_TYPE_FIELD,
RULE_NAME_FIELD,
RULE_PARAMS_FIELDS,
TAGS_FIELD,
} from './rule_fields';

// KQL does not allow to search for existence of the prebuilt object field, since params is unmapped
// so we can search for the existence of the isCustomized subfield instead, which is required
export const KQL_FILTER_PREBUILT_RULES = `${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`;
export const KQL_FILTER_CUSTOM_RULES = `NOT ${PARAMS_PREBUILT_IS_CUSTOMIZED_FIELD}: *`;
export const KQL_FILTER_IMMUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: true`;
export const KQL_FILTER_MUTABLE_RULES = `${PARAMS_IMMUTABLE_FIELD}: false`;
export const KQL_FILTER_ENABLED_RULES = `${ENABLED_FIELD}: true`;
Expand Down Expand Up @@ -59,9 +64,11 @@ export function convertRulesFilterToKQL({
if (showCustomRules && showElasticRules) {
// if both showCustomRules && showElasticRules selected we omit filter, as it includes all existing rules
} else if (showElasticRules) {
kql.push(KQL_FILTER_IMMUTABLE_RULES);
kql.push(`${KQL_FILTER_PREBUILT_RULES}`);
// kql.push(`(${KQL_FILTER_PREBUILT_RULES} OR ${KQL_FILTER_IMMUTABLE_RULES})`);
} else if (showCustomRules) {
kql.push(KQL_FILTER_MUTABLE_RULES);
kql.push(`${KQL_FILTER_CUSTOM_RULES}`);
// kql.push(`(${KQL_FILTER_CUSTOM_RULES} OR ${KQL_FILTER_MUTABLE_RULES})`);
}

if (enabled !== undefined) {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading