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

[SecuritySolution][SIEM migrations] Add macros and lookups support in the API #199370

Merged
merged 46 commits into from
Nov 18, 2024
Merged
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
0fb249c
create resources data stream
semd Nov 6, 2024
e670f22
add migration resources data client
semd Nov 7, 2024
52df6cf
Merge remote-tracking branch 'upstream/main' into 10653/siem_migratio…
semd Nov 8, 2024
78f80a3
resource retrieval implemented
semd Nov 9, 2024
b37628d
new index-adaper package
semd Nov 9, 2024
da18c38
[CI] Auto-commit changed files from 'node scripts/capture_oas_snapsho…
kibanamachine Nov 9, 2024
45a358b
fix packages configs
semd Nov 9, 2024
98c1aa3
Merge remote-tracking branch 'refs/remotes/origin/index_adapter_base_…
semd Nov 9, 2024
8453062
rollback ds adapter changes
semd Nov 9, 2024
df7061e
[CI] Auto-commit changed files from 'node scripts/generate codeowners'
kibanamachine Nov 9, 2024
76f8f5b
Merge branch 'index_adapter_base_package' into 10653/siem_migrations/…
semd Nov 9, 2024
9ceac8f
Merge remote-tracking branch 'upstream/main' into 10653/siem_migratio…
semd Nov 9, 2024
78053f8
[CI] Auto-commit changed files from 'node scripts/yarn_deduplicate'
kibanamachine Nov 9, 2024
d57c791
improve createIndex
semd Nov 9, 2024
3fe56b7
Merge branch 'index_adapter_base_package' into 10653/siem_migrations/…
semd Nov 9, 2024
71bcd58
use index insted of ds
semd Nov 9, 2024
3bae810
fix type
semd Nov 9, 2024
6aa4beb
Merge branch 'index_adapter_base_package' into 10653/siem_migrations/…
semd Nov 9, 2024
47c6321
SRP for createIndex function
semd Nov 10, 2024
af817a8
Merge branch 'index_adapter_base_package' into 10653/siem_migrations/…
semd Nov 10, 2024
92cc378
adapt createIndex
semd Nov 10, 2024
9816c28
fix tests
semd Nov 10, 2024
6db7180
solve conflicts
semd Nov 11, 2024
b1d9499
rollback dependency
semd Nov 11, 2024
51d2318
conflict solved
semd Nov 11, 2024
81dbabe
Merge branch 'index_adapter_base_package' into 10653/siem_migrations/…
semd Nov 11, 2024
3e1d973
improve query translation by inlining macros
semd Nov 11, 2024
ebe2f99
import from package entry file
semd Nov 11, 2024
57409f1
Merge branch 'index_adapter_base_package' into 10653/siem_migrations/…
semd Nov 11, 2024
af521d2
simplify data clients
semd Nov 13, 2024
d50a05c
merge main
semd Nov 13, 2024
b5aba7e
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 13, 2024
b96ab2c
[CI] Auto-commit changed files from 'yarn openapi:generate'
kibanamachine Nov 13, 2024
a777870
add mocks and tests
semd Nov 13, 2024
d12b4da
Merge remote-tracking branch 'upstream/main' into 10653/siem_migratio…
semd Nov 13, 2024
553ffa3
Merge remote-tracking branch 'refs/remotes/origin/10653/siem_migratio…
semd Nov 13, 2024
bcf4968
update mocks
semd Nov 13, 2024
654b377
fix tests
semd Nov 13, 2024
dd1f7a1
add missing mocks
semd Nov 13, 2024
4c0dcb6
installation error handling moved up
semd Nov 14, 2024
232be91
Merge remote-tracking branch 'upstream/main' into 10653/siem_migratio…
semd Nov 14, 2024
cb37dfc
Merge branch 'main' into 10653/siem_migrations/add_macros_support
elasticmachine Nov 14, 2024
faa38c7
address comments
semd Nov 18, 2024
08bd32f
Merge remote-tracking branch 'upstream/main' into 10653/siem_migratio…
semd Nov 18, 2024
186699b
Merge remote-tracking branch 'refs/remotes/origin/10653/siem_migratio…
semd Nov 18, 2024
61aae02
Merge branch 'main' into 10653/siem_migrations/add_macros_support
michaelolo24 Nov 18, 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
Next Next commit
create resources data stream
  • Loading branch information
semd committed Nov 6, 2024
commit 0fb249c44bc7a12bf25302a9ac72cd74245c87cb
Original file line number Diff line number Diff line change
@@ -168,8 +168,6 @@ export async function createDataStream({
esClient,
name,
}: CreateDataStreamParams): Promise<void> {
logger.info(`Creating data stream - ${name}`);

// check if data stream exists
let dataStreamExists = false;
try {
@@ -190,6 +188,7 @@ export async function createDataStream({
return;
}

logger.info(`Creating data stream - ${name}`);
try {
await retryTransientEsErrors(() => esClient.indices.createDataStream({ name }), { logger });
} catch (error) {
41 changes: 24 additions & 17 deletions packages/kbn-data-stream-adapter/src/data_stream_spaces_adapter.ts
Original file line number Diff line number Diff line change
@@ -16,24 +16,25 @@ import {
type InstallParams,
} from './data_stream_adapter';

type InstallSpace = (spaceId: string) => Promise<string>;

export class DataStreamSpacesAdapter extends DataStreamAdapter {
private installedSpaceDataStreamName: Map<string, Promise<string>>;
private _installSpace?: (spaceId: string) => Promise<string>;
private installSpacePromise?: Promise<InstallSpace>;

constructor(private readonly prefix: string, options: DataStreamAdapterParams) {
super(`${prefix}-*`, options); // make indexTemplate `indexPatterns` match all data stream space names
this.installedSpaceDataStreamName = new Map();
}

public async install({
logger,
esClient: esClientToResolve,
pluginStop$,
tasksTimeoutMs,
}: InstallParams) {
this.installed = true;
public async install(params: InstallParams): Promise<void> {
this.installSpacePromise = this._install(params);
await this.installSpacePromise;
}

const esClient = await esClientToResolve;
private async _install(params: InstallParams): Promise<InstallSpace> {
const { logger, pluginStop$, tasksTimeoutMs } = params;
const esClient = await params.esClient;
const installFn = this.getInstallFn({ logger, pluginStop$, tasksTimeoutMs });

// Install component templates in parallel
@@ -55,7 +56,11 @@ export class DataStreamSpacesAdapter extends DataStreamAdapter {
await Promise.all(
this.indexTemplates.map((indexTemplate) =>
installFn(
createOrUpdateIndexTemplate({ template: indexTemplate, esClient, logger }),
createOrUpdateIndexTemplate({
template: indexTemplate,
esClient,
logger,
}),
`create or update ${indexTemplate.name} index template`
)
)
@@ -73,27 +78,29 @@ export class DataStreamSpacesAdapter extends DataStreamAdapter {
);

// define function to install data stream for spaces on demand
this._installSpace = async (spaceId: string) => {
const installSpace = async (spaceId: string) => {
const existingInstallPromise = this.installedSpaceDataStreamName.get(spaceId);
if (existingInstallPromise) {
return existingInstallPromise;
}
const name = `${this.prefix}-${spaceId}`;
const installPromise = installFn(
const namePromise = installFn(
createDataStream({ name, esClient, logger }),
`create ${name} data stream`
).then(() => name);

this.installedSpaceDataStreamName.set(spaceId, installPromise);
return installPromise;
this.installedSpaceDataStreamName.set(spaceId, namePromise);
return namePromise;
};
return installSpace;
}

public async installSpace(spaceId: string): Promise<string> {
if (!this._installSpace) {
if (!this.installSpacePromise) {
throw new Error('Cannot installSpace before install');
}
return this._installSpace(spaceId);
// Await for installSpacePromise to ensure installation is complete, since install call may not be awaited from the plugin
const installSpace = await this.installSpacePromise;
return installSpace(spaceId);
}

public async getInstalledSpaceName(spaceId: string): Promise<string | undefined> {
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Common SIEM Migrations Attributes
* title: SIEM Rule Migrations API common components
* version: not applicable
*/

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.3
info:
title: Common SIEM Migrations Attributes
title: SIEM Rule Migrations API common components
version: 'not applicable'
paths: {}
components:
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: SIEM Rules Migration API endpoint
* title: SIEM Rules Migration API
* version: 1
*/

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.3
info:
title: SIEM Rules Migration API endpoint
title: SIEM Rules Migration API
version: '1'
paths:
/internal/siem_migrations/rules:
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Common Splunk Rules Attributes
* title: SIEM Rule Migration common components
* version: not applicable
*/

@@ -178,3 +178,38 @@ export const RuleMigrationAllTaskStats = z.array(
})
)
);

/**
* The rule migration resource document object.
*/
export type RuleMigrationResource = z.infer<typeof RuleMigrationResource>;
export const RuleMigrationResource = z.object({
/**
* The migration id for with the resource is associated.
*/
migration_id: z.string(),
/**
* The type of the resource.
*/
type: z.enum(['macro', 'list']),
/**
* The resource name identifier.
*/
name: z.string(),
/**
* The resource content value.
*/
content: z.string().optional(),
/**
* The resource arbitrary metadata.
*/
metadata: z.object({}).optional(),
/**
* The moment of the last update
*/
updated_at: z.string().optional(),
/**
* The user who last updated the resource
*/
updated_by: z.string().optional(),
});
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
openapi: 3.0.3
info:
title: Common Splunk Rules Attributes
title: SIEM Rule Migration common components
version: 'not applicable'
paths: {}
components:
@@ -180,3 +180,36 @@ components:
migration_id:
type: string
description: The migration id

RuleMigrationResource:
type: object
description: The rule migration resource document object.
required:
- migration_id
- type
- name
properties:
migration_id:
type: string
description: The migration id for with the resource is associated.
type:
type: string
description: The type of the resource.
enum:
- macro
- list
name:
type: string
description: The resource name identifier.
content:
type: string
description: The resource content value.
metadata:
type: object
description: The resource arbitrary metadata.
updated_at:
type: string
description: The moment of the last update
updated_by:
type: string
description: The user who last updated the resource
Original file line number Diff line number Diff line change
@@ -29,15 +29,15 @@ export type RuleMigrationAllDataStats = Array<RuleMigrationDataStats & { migrati

export class RuleMigrationsDataClient {
constructor(
private dataStreamNamePromise: Promise<string>,
private indexNamePromises: Record<'rules' | 'resources', Promise<string>>,
private currentUser: AuthenticatedUser,
private esClient: ElasticsearchClient,
private logger: Logger
) {}

/** Indexes an array of rule migrations to be processed */
async create(ruleMigrations: CreateRuleMigrationInput[]): Promise<void> {
const index = await this.dataStreamNamePromise;
const index = await this.indexNamePromises.rules;
await this.esClient
.bulk({
refresh: 'wait_for',
@@ -59,7 +59,7 @@ export class RuleMigrationsDataClient {

/** Retrieves an array of rule documents of a specific migrations */
async getRules(migrationId: string): Promise<StoredRuleMigration[]> {
const index = await this.dataStreamNamePromise;
const index = await this.indexNamePromises.rules;
const query = this.getFilterQuery(migrationId);

const storedRuleMigrations = await this.esClient
@@ -79,7 +79,7 @@ export class RuleMigrationsDataClient {
* - Multiple tasks should not process the same migration simultaneously.
*/
async takePending(migrationId: string, size: number): Promise<StoredRuleMigration[]> {
const index = await this.dataStreamNamePromise;
const index = await this.indexNamePromises.rules;
const query = this.getFilterQuery(migrationId, SiemMigrationStatus.PENDING);

const storedRuleMigrations = await this.esClient
@@ -117,7 +117,7 @@ export class RuleMigrationsDataClient {
}

/** Updates one rule migration with the provided data and sets the status to `completed` */
async saveFinished({ _id, _index, ...ruleMigration }: StoredRuleMigration): Promise<void> {
async saveCompleted({ _id, _index, ...ruleMigration }: StoredRuleMigration): Promise<void> {
const doc = {
...ruleMigration,
status: SiemMigrationStatus.COMPLETED,
@@ -150,7 +150,7 @@ export class RuleMigrationsDataClient {

/** Updates all the rule migration with the provided id with status `processing` back to `pending` */
async releaseProcessing(migrationId: string): Promise<void> {
const index = await this.dataStreamNamePromise;
const index = await this.indexNamePromises.rules;
const query = this.getFilterQuery(migrationId, SiemMigrationStatus.PROCESSING);
const script = { source: `ctx._source['status'] = '${SiemMigrationStatus.PENDING}'` };
await this.esClient.updateByQuery({ index, query, script, refresh: false }).catch((error) => {
@@ -161,7 +161,7 @@ export class RuleMigrationsDataClient {

/** Updates all the rule migration with the provided id with status `processing` or `failed` back to `pending` */
async releaseProcessable(migrationId: string): Promise<void> {
const index = await this.dataStreamNamePromise;
const index = await this.indexNamePromises.rules;
const query = this.getFilterQuery(migrationId, [
SiemMigrationStatus.PROCESSING,
SiemMigrationStatus.FAILED,
@@ -175,7 +175,7 @@ export class RuleMigrationsDataClient {

/** Retrieves the stats for the rule migrations with the provided id */
async getStats(migrationId: string): Promise<RuleMigrationDataStats> {
const index = await this.dataStreamNamePromise;
const index = await this.indexNamePromises.rules;
const query = this.getFilterQuery(migrationId);
const aggregations = {
pending: { filter: { term: { status: SiemMigrationStatus.PENDING } } },
@@ -206,7 +206,7 @@ export class RuleMigrationsDataClient {

/** Retrieves the stats for all the rule migrations aggregated by migration id */
async getAllStats(): Promise<RuleMigrationAllDataStats> {
const index = await this.dataStreamNamePromise;
const index = await this.indexNamePromises.rules;
const aggregations = {
migrationIds: {
terms: { field: 'migration_id' },
Loading