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

[Rules migration] Use user profile UID instead of username #206299

Merged
merged 3 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -11,20 +11,41 @@ import type {
SearchResponse,
Duration,
} from '@elastic/elasticsearch/lib/api/types';
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import type {
AuthenticatedUser,
ElasticsearchClient,
IScopedClusterClient,
Logger,
} from '@kbn/core/server';
import assert from 'assert';
import type { Stored } from '../types';
import type { IndexNameProvider } from './rule_migrations_data_client';

const DEFAULT_PIT_KEEP_ALIVE: Duration = '30s' as const;

export class RuleMigrationsDataBaseClient {
protected esClient: ElasticsearchClient;

constructor(
protected getIndexName: IndexNameProvider,
protected username: string,
protected esClient: ElasticsearchClient,
protected currentUser: AuthenticatedUser,
protected esScopedClient: IScopedClusterClient,
protected logger: Logger
) {}
) {
this.esClient = esScopedClient.asInternalUser;
}

protected async getProfileUid() {
if (this.currentUser.profile_uid) {
return this.currentUser.profile_uid;
}
const username = this.currentUser.username;
const users = await this.esScopedClient.asCurrentUser.security.getUser({
username,
with_profile_uid: true,
});
return users[username].profile_uid;
}

protected processResponseHits<T extends object>(
response: SearchResponse<T>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import type { IScopedClusterClient, Logger } from '@kbn/core/server';
import type { AuthenticatedUser, IScopedClusterClient, Logger } from '@kbn/core/server';
import type { PackageService } from '@kbn/fleet-plugin/server';
import { RuleMigrationsDataIntegrationsClient } from './rule_migrations_data_integrations_client';
import { RuleMigrationsDataPrebuiltRulesClient } from './rule_migrations_data_prebuilt_rules_client';
Expand All @@ -26,40 +26,36 @@ export class RuleMigrationsDataClient {

constructor(
indexNameProviders: IndexNameProviders,
username: string,
currentUser: AuthenticatedUser,
esScopedClient: IScopedClusterClient,
logger: Logger,
packageService?: PackageService
) {
this.rules = new RuleMigrationsDataRulesClient(
indexNameProviders.rules,
username,
esScopedClient.asInternalUser,
currentUser,
esScopedClient,
logger
);
this.resources = new RuleMigrationsDataResourcesClient(
indexNameProviders.resources,
username,
esScopedClient.asInternalUser,
currentUser,
esScopedClient,
logger
);
this.integrations = new RuleMigrationsDataIntegrationsClient(
indexNameProviders.integrations,
username,
esScopedClient.asInternalUser,
currentUser,
esScopedClient,
logger,
packageService
);
this.prebuiltRules = new RuleMigrationsDataPrebuiltRulesClient(
indexNameProviders.prebuiltrules,
username,
esScopedClient.asInternalUser,
logger
);
this.lookups = new RuleMigrationsDataLookupsClient(
username,
esScopedClient.asCurrentUser,
currentUser,
esScopedClient,
logger
);
this.lookups = new RuleMigrationsDataLookupsClient(currentUser, esScopedClient, logger);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import type { PackageService } from '@kbn/fleet-plugin/server';
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import type { AuthenticatedUser, IScopedClusterClient, Logger } from '@kbn/core/server';
import type { PackageList } from '@kbn/fleet-plugin/common';
import type { RuleMigrationIntegration } from '../types';
import { RuleMigrationsDataBaseClient } from './rule_migrations_data_base_client';
Expand All @@ -28,12 +28,12 @@ const INTEGRATIONS = integrationsFile as RuleMigrationIntegration[];
export class RuleMigrationsDataIntegrationsClient extends RuleMigrationsDataBaseClient {
constructor(
getIndexName: IndexNameProvider,
username: string,
esClient: ElasticsearchClient,
currentUser: AuthenticatedUser,
esScopedClient: IScopedClusterClient,
logger: Logger,
private packageService?: PackageService
) {
super(getIndexName, username, esClient, logger);
super(getIndexName, currentUser, esScopedClient, logger);
}

async getIntegrationPackages(): Promise<PackageList | undefined> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@
*/

import { sha256 } from 'js-sha256';
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
import type { AuthenticatedUser, IScopedClusterClient, Logger } from '@kbn/core/server';
import { retryTransientEsErrors } from '@kbn/index-adapter';

export type LookupData = object[];

export class RuleMigrationsDataLookupsClient {
constructor(
protected username: string,
protected esClient: ElasticsearchClient,
protected currentUser: AuthenticatedUser,
protected esScopedClient: IScopedClusterClient,
protected logger: Logger
) {}

async create(lookupName: string, data: LookupData): Promise<string> {
const indexName = `lookup_${lookupName}`;
try {
await this.executeEs(() =>
this.esClient.indices.create({
this.esScopedClient.asCurrentUser.indices.create({
index: indexName,
settings: { index: { mode: 'lookup' } },
mappings: { dynamic: 'runtime' },
Expand All @@ -48,7 +48,9 @@ export class RuleMigrationsDataLookupsClient {
]);

try {
await this.executeEs(() => this.esClient.bulk({ index: indexName, body }));
await this.executeEs(() =>
this.esScopedClient.asCurrentUser.bulk({ index: indexName, body })
);
} catch (error) {
if (error?.statusCode !== 404) {
this.logger.error(`Error indexing data for lookup index ${indexName} - ${error.message}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const DEFAULT_SEARCH_BATCH_SIZE = 500 as const;
export class RuleMigrationsDataResourcesClient extends RuleMigrationsDataBaseClient {
public async upsert(resources: CreateRuleMigrationResourceInput[]): Promise<void> {
const index = await this.getIndexName();
const profileId = await this.getProfileUid();

let resourcesSlice: CreateRuleMigrationResourceInput[];

Expand All @@ -54,7 +55,7 @@ export class RuleMigrationsDataResourcesClient extends RuleMigrationsDataBaseCli
doc: {
...resource,
'@timestamp': createdAt,
updated_by: this.username,
updated_by: profileId,
updated_at: createdAt,
},
doc_as_upsert: true,
Expand All @@ -71,6 +72,7 @@ export class RuleMigrationsDataResourcesClient extends RuleMigrationsDataBaseCli
/** Creates the resources in the index only if they do not exist */
public async create(resources: CreateRuleMigrationResourceInput[]): Promise<void> {
const index = await this.getIndexName();
const profileId = await this.getProfileUid();

let resourcesSlice: CreateRuleMigrationResourceInput[];
const createdAt = new Date().toISOString();
Expand All @@ -83,7 +85,7 @@ export class RuleMigrationsDataResourcesClient extends RuleMigrationsDataBaseCli
{
...resource,
'@timestamp': createdAt,
updated_by: this.username,
updated_by: profileId,
updated_at: createdAt,
},
]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
/** Indexes an array of rule migrations to be processed */
async create(ruleMigrations: CreateRuleMigrationInput[]): Promise<void> {
const index = await this.getIndexName();
const profileId = await this.getProfileUid();

let ruleMigrationsSlice: CreateRuleMigrationInput[];
const createdAt = new Date().toISOString();
Expand All @@ -79,8 +80,8 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
...ruleMigration,
'@timestamp': createdAt,
status: SiemMigrationStatus.PENDING,
created_by: this.username,
updated_by: this.username,
created_by: profileId,
updated_by: profileId,
updated_at: createdAt,
},
]),
Expand All @@ -95,6 +96,7 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
/** Updates an array of rule migrations to be processed */
async update(ruleMigrations: UpdateRuleMigrationData[]): Promise<void> {
const index = await this.getIndexName();
const profileId = await this.getProfileUid();

let ruleMigrationsSlice: UpdateRuleMigrationData[];
const updatedAt = new Date().toISOString();
Expand All @@ -117,7 +119,7 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
elastic_rule: elasticRule,
translation_result:
translationResult ?? convertEsqlQueryToTranslationResult(elasticRule?.query),
updated_by: this.username,
updated_by: profileId,
updated_at: updatedAt,
},
},
Expand Down Expand Up @@ -176,6 +178,7 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
*/
async takePending(migrationId: string, size: number): Promise<StoredRuleMigration[]> {
const index = await this.getIndexName();
const profileId = await this.getProfileUid();
const query = this.getFilterQuery(migrationId, { status: SiemMigrationStatus.PENDING });

const storedRuleMigrations = await this.esClient
Expand All @@ -194,7 +197,7 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
operations: storedRuleMigrations.flatMap(({ id, status }) => [
{ update: { _id: id, _index: index } },
{
doc: { status, updated_by: this.username, updated_at: new Date().toISOString() },
doc: { status, updated_by: profileId, updated_at: new Date().toISOString() },
},
]),
})
Expand All @@ -211,10 +214,11 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
/** Updates one rule migration with the provided data and sets the status to `completed` */
async saveCompleted({ id, ...ruleMigration }: StoredRuleMigration): Promise<void> {
const index = await this.getIndexName();
const profileId = await this.getProfileUid();
const doc = {
...ruleMigration,
status: SiemMigrationStatus.COMPLETED,
updated_by: this.username,
updated_by: profileId,
updated_at: new Date().toISOString(),
};
await this.esClient.update({ index, id, doc, refresh: 'wait_for' }).catch((error) => {
Expand All @@ -226,10 +230,11 @@ export class RuleMigrationsDataRulesClient extends RuleMigrationsDataBaseClient
/** Updates one rule migration with the provided data and sets the status to `failed` */
async saveError({ id, ...ruleMigration }: StoredRuleMigration): Promise<void> {
const index = await this.getIndexName();
const profileId = await this.getProfileUid();
const doc = {
...ruleMigration,
status: SiemMigrationStatus.FAILED,
updated_by: this.username,
updated_by: profileId,
updated_at: new Date().toISOString(),
};
await this.esClient.update({ index, id, doc, refresh: 'wait_for' }).catch((error) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export class RuleMigrationsDataService {

return new RuleMigrationsDataClient(
indexNameProviders,
currentUser.username,
currentUser,
esScopedClient,
this.logger,
packageService
Expand Down
Loading