Skip to content

Commit

Permalink
[SecuritySolution] Revamp entity analytics Open API schemas (#182666)
Browse files Browse the repository at this point in the history
## Summary

* Declare all API types using Open API Schema (OAS). 
* Generate TS types from schemas
* Update the code to use the generated types
* Validate requests with `buildRouteValidationWithZod `
* Delete
`x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/common.schema.yaml`.
There were 2 common files.
* Auto format `yaml` files for consistency. 
* Rename `yaml` files from `{name}_schema.yml` to `{name}.schema.yml`.
Otherwise, they don't work with the generator.
* Rename `RiskScore`  to `EntityRiskScoreRecord` (requested by Maxim)
* Update yaml version to '1'
  • Loading branch information
machadoum committed May 16, 2024
1 parent 78ff455 commit a65b688
Show file tree
Hide file tree
Showing 115 changed files with 1,542 additions and 2,066 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { z } from 'zod';
*
* info:
* title: Asset Criticality Common Schema
* version: 1.0.0
* version: 1
*/

export type IdField = z.infer<typeof IdField>;
Expand All @@ -33,13 +33,23 @@ export const AssetCriticalityRecordIdParts = z.object({
id_field: IdField,
});

/**
* The criticality level of the asset.
*/
export type AssetCriticalityLevel = z.infer<typeof AssetCriticalityLevel>;
export const AssetCriticalityLevel = z.enum([
'low_impact',
'medium_impact',
'high_impact',
'extreme_impact',
]);
export type AssetCriticalityLevelEnum = typeof AssetCriticalityLevel.enum;
export const AssetCriticalityLevelEnum = AssetCriticalityLevel.enum;

export type CreateAssetCriticalityRecord = z.infer<typeof CreateAssetCriticalityRecord>;
export const CreateAssetCriticalityRecord = AssetCriticalityRecordIdParts.merge(
z.object({
/**
* The criticality level of the asset.
*/
criticality_level: z.enum(['low_impact', 'medium_impact', 'high_impact', 'extreme_impact']),
criticality_level: AssetCriticalityLevel,
/**
* If 'wait_for' the request will wait for the index refresh.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ openapi: 3.0.0
info:
title: Asset Criticality Common Schema
description: Common schema for asset criticality
version: 1.0.0
paths: { }
version: '1'
paths: {}
components:
parameters:
id_value:
Expand Down Expand Up @@ -41,19 +41,26 @@ components:
required:
- id_value
- id_field
AssetCriticalityLevel:
type: string
enum:
- low_impact
- medium_impact
- high_impact
- extreme_impact
description: The criticality level of the asset.

CreateAssetCriticalityRecord:
allOf:
- $ref: '#/components/schemas/AssetCriticalityRecordIdParts'
- type: object
properties:
criticality_level:
type: string
enum: [low_impact, medium_impact, high_impact, extreme_impact]
description: The criticality level of the asset.
$ref: '#/components/schemas/AssetCriticalityLevel'
refresh:
type: string
enum: [wait_for]
description: If 'wait_for' the request will wait for the index refresh.
type: string
enum: [wait_for]
description: If 'wait_for' the request will wait for the index refresh.
required:
- criticality_level
DeleteAssetCriticalityRecord:
Expand All @@ -62,18 +69,18 @@ components:
- type: object
properties:
refresh:
type: string
enum: [wait_for]
description: If 'wait_for' the request will wait for the index refresh.
type: string
enum: [wait_for]
description: If 'wait_for' the request will wait for the index refresh.
AssetCriticalityRecord:
allOf:
- $ref: '#/components/schemas/CreateAssetCriticalityRecord'
- type: object
properties:
"@timestamp":
'@timestamp':
type: string
format: 'date-time'
example: '2017-07-21T17:32:28Z'
description: The time the record was created or updated.
required:
- "@timestamp"
- '@timestamp'
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.0
info:
version: 1.0.0
version: '1'
title: Asset Criticality Create Record Schema
servers:
- url: 'http://{kibana_host}:{port}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.0
info:
version: 1.0.0
version: '1'
title: Asset Criticality Delete Record Schema
servers:
- url: 'http://{kibana_host}:{port}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.0
info:
version: 1.0.0
version: '1'
title: Asset Criticality Get Record Schema
servers:
- url: 'http://{kibana_host}:{port}'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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 { z } from 'zod';

/*
* NOTICE: Do not edit this file manually.
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Get Asset Criticality Privileges Schema
* version: 1
*/

export type EntityAnalyticsPrivileges = z.infer<typeof EntityAnalyticsPrivileges>;
export const EntityAnalyticsPrivileges = z.object({
has_all_required: z.boolean(),
has_read_permissions: z.boolean().optional(),
has_write_permissions: z.boolean().optional(),
privileges: z.object({
elasticsearch: z.object({
cluster: z
.object({
manage_index_templates: z.boolean().optional(),
manage_transform: z.boolean().optional(),
})
.optional(),
index: z
.object({})
.catchall(
z.object({
read: z.boolean().optional(),
write: z.boolean().optional(),
})
)
.optional(),
}),
}),
});
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: 3.0.0
info:
title: Get Asset Criticality Privileges Schema
version: 1.0.0
version: '1'
servers:
- url: 'http://{kibana_host}:{port}'
variables:
Expand All @@ -20,11 +20,49 @@ paths:
content:
application/json:
schema:
$ref: '../common/common.schema.yaml#/components/schemas/EntityAnalyticsPrivileges'
$ref: '#/components/schemas/EntityAnalyticsPrivileges'
example:
elasticsearch:
index:
".asset-criticality.asset-criticality-*":
'.asset-criticality.asset-criticality-*':
read: true
write: false
has_all_required: false
components:
schemas:
EntityAnalyticsPrivileges:
type: object
properties:
has_all_required:
type: boolean
has_read_permissions:
type: boolean
has_write_permissions:
type: boolean
privileges:
type: object
properties:
elasticsearch:
type: object
properties:
cluster:
type: object
properties:
manage_index_templates:
type: boolean
manage_transform:
type: boolean
index:
type: object
additionalProperties:
type: object
properties:
read:
type: boolean
write:
type: boolean
required:
- elasticsearch
required:
- has_all_required
- privileges
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { z } from 'zod';
*
* info:
* title: Asset Criticality Status Schema
* version: 1.0.0
* version: 1
*/

export type AssetCriticalityStatusResponse = z.infer<typeof AssetCriticalityStatusResponse>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.0
info:
version: 1.0.0
version: '1'
title: Asset Criticality Status Schema
servers:
- url: 'http://{kibana_host}:{port}'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@
export * from './common.gen';
export * from './get_asset_criticality_status.gen';
export * from './upload_asset_criticality_csv.gen';
export * from './get_asset_criticality_privileges.gen';
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { z } from 'zod';
*
* info:
* title: Asset Criticality Create Record Schema
* version: 1.0.0
* version: 1
*/

export type ErrorItem = z.infer<typeof ErrorItem>;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.0
info:
version: 1.0.0
version: '1'
title: Asset Criticality Create Record Schema
servers:
- url: 'http://{kibana_host}:{port}'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* 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 { AfterKeys } from '.';
import type { SafeParseSuccess } from 'zod';

describe('after_keys schema', () => {
it('allows an empty object', () => {
const payload = {};
const decoded = AfterKeys.safeParse(payload) as SafeParseSuccess<object>;

expect(decoded.success).toBeTruthy();
expect(decoded.data).toEqual(payload);
});

it('allows a valid host key', () => {
const payload = { host: { 'host.name': 'hello' } };
const decoded = AfterKeys.safeParse(payload) as SafeParseSuccess<object>;

expect(decoded.success).toBeTruthy();
expect(decoded.data).toEqual(payload);
});

it('allows a valid user key', () => {
const payload = { user: { 'user.name': 'hello' } };
const decoded = AfterKeys.safeParse(payload) as SafeParseSuccess<object>;

expect(decoded.success).toBeTruthy();
expect(decoded.data).toEqual(payload);
});

it('allows both valid host and user keys', () => {
const payload = { user: { 'user.name': 'hello' }, host: { 'host.name': 'hello' } };
const decoded = AfterKeys.safeParse(payload) as SafeParseSuccess<object>;

expect(decoded.success).toBeTruthy();
expect(decoded.data).toEqual(payload);
});

it('removes an unknown identifier key if used', () => {
const payload = { bad: 'key' };

const decoded = AfterKeys.safeParse(payload) as SafeParseSuccess<object>;

expect(decoded.success).toBeTruthy();
expect(decoded.data).toEqual({});
});
});
Loading

0 comments on commit a65b688

Please sign in to comment.