Skip to content

Commit

Permalink
[Security Solution] Replaced the incorrect runtime type used for rule…
Browse files Browse the repository at this point in the history
…Source (elastic#184004)

## Summary

This PR replaces the incorrect Zod schema for the `ruleSource` rule
param.

Previously, the rule source field schema was implemented using a Zod
transformation that automatically converted the snake-cased
`is_customized` attribute to its camel-cased version `isCustomized`.

```ts
const RuleSourceCamelCased = RuleSource.transform(convertObjectKeysToCamelCase);

const RuleSource = z.object({
  type: z.literal('external'),
  is_customized: IsExternalRuleCustomized,
});
```

However, this meant that the expected input type for the schema was
snake-cased, as the transformation happened only after validation.

**Valid payload before:**

```json5
{
  "ruleSource": {
    "type": "external",
    "is_customized": false // <- it should be camel cased
  }
}
```

To overcome this issue, the rule source schema was implemented without
using the transformation (revert
elastic#180121).

**Valid payload after:**

```json5
{
  "ruleSource": {
    "type": "external",
    "isCustomized": false
  }
}
```

### Important Note

This rule param schema change is considered safe because we do not
currently use this field in the code. All values of this field are
currently `undefined`. However, to ensure a Serverless release rollout
without breaking changes, we need to release this schema change before
we start writing any actual data.
  • Loading branch information
xcrzx committed May 23, 2024
1 parent b6e0f87 commit 6150a22
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 17 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
IndexPatternArray,
InvestigationFields,
InvestigationGuide,
IsExternalRuleCustomized,
IsRuleImmutable,
ItemsPerSearch,
KqlQueryLanguage,
Expand All @@ -63,7 +64,6 @@ import {
RuleQuery,
RuleReferenceArray,
RuleSignatureId,
RuleSource,
RuleVersion,
SavedQueryId,
SetupGuide,
Expand All @@ -84,7 +84,6 @@ import {
TimestampOverrideFallbackDisabled,
} from '../../../../../common/api/detection_engine/model/rule_schema';
import type { SERVER_APP_ID } from '../../../../../common/constants';
import { convertObjectKeysToCamelCase } from '../../../../utils/object_case_converters';

// 8.10.x is mapped as an array of strings
export type LegacyInvestigationFields = z.infer<typeof LegacyInvestigationFields>;
Expand All @@ -104,8 +103,20 @@ export const InvestigationFieldsCombined = z.union([
LegacyInvestigationFields,
]);

/**
* This is the same type as RuleSource, but with the keys in camelCase. Intended
* for internal use only (not for API responses).
*/
export type RuleSourceCamelCased = z.infer<typeof RuleSourceCamelCased>;
export const RuleSourceCamelCased = RuleSource.transform(convertObjectKeysToCamelCase);
export const RuleSourceCamelCased = z.discriminatedUnion('type', [
z.object({
type: z.literal('external'),
isCustomized: IsExternalRuleCustomized,
}),
z.object({
type: z.literal('internal'),
}),
]);

// Conversion to an interface has to be disabled for the entire file; otherwise,
// the resulting union would not be assignable to Alerting's RuleParams due to a
Expand Down

0 comments on commit 6150a22

Please sign in to comment.