[Security Solution] Support experimental features in timelines (#189028)

## Summary

Adding generic support for experimental features in timelines

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Luke G 2024-07-26 17:46:40 +02:00 committed by GitHub
parent 7e5907e816
commit 7db28682dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 97 additions and 5 deletions

View file

@ -336,6 +336,7 @@ export default function ({ getService }: PluginFunctionalProviderContext) {
'xpack.stack_connectors.enableExperimental (array)',
'xpack.trigger_actions_ui.enableExperimental (array)',
'xpack.trigger_actions_ui.enableGeoTrackingThresholdAlert (boolean)',
'xpack.timelines.enableExperimental (array)',
'xpack.alerting.rules.run.alerts.max (number)',
'xpack.upgrade_assistant.featureSet.migrateSystemIndices (boolean)',
'xpack.upgrade_assistant.featureSet.mlSnapshots (boolean)',

View file

@ -935,4 +935,3 @@ components:
type: http
security:
- BasicAuth: []
tags: !<tag:yaml.org,2002:js/undefined> ''

View file

@ -863,4 +863,3 @@ components:
type: http
security:
- BasicAuth: []
tags: !<tag:yaml.org,2002:js/undefined> ''

View file

@ -0,0 +1,47 @@
/*
* 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.
*/
export const allowedExperimentalValues = Object.freeze({
// NOTE: remove this after some actual flags are added, without it line 36 fails ts validation
sample: false,
});
export type ExperimentalFeatures = { [K in keyof typeof allowedExperimentalValues]: boolean };
const allowedKeys = Object.keys(allowedExperimentalValues);
type Mutable<T> = { -readonly [P in keyof T]: T[P] };
/**
* Parses the string value used in `xpack.timelines.enableExperimental` kibana configuration,
* which should be a string of values delimited by a comma (`,`)
*
* @param configValue
* @throws SecuritySolutionInvalidExperimentalValue
*/
export const parseExperimentalConfigValue = (
configValue: string[]
): { features: ExperimentalFeatures; invalid: string[] } => {
const enabledFeatures: Mutable<Partial<ExperimentalFeatures>> = {};
const invalidKeys: string[] = [];
for (const value of configValue) {
if (!allowedKeys.includes(value as keyof ExperimentalFeatures)) {
invalidKeys.push(value);
} else {
enabledFeatures[value as keyof ExperimentalFeatures] = true;
}
}
return {
features: {
...allowedExperimentalValues,
...enabledFeatures,
},
invalid: invalidKeys,
};
};

View file

@ -0,0 +1,10 @@
/*
* 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.
*/
export interface ConfigSchema {
enableExperimental: string[];
}

View file

@ -5,7 +5,9 @@
* 2.0.
*/
import { PluginInitializerContext } from '@kbn/core/server';
import { PluginConfigDescriptor, PluginInitializerContext } from '@kbn/core/server';
import { schema } from '@kbn/config-schema';
import { ConfigSchema } from './config';
export async function plugin(initializerContext: PluginInitializerContext) {
const { TimelinesPlugin } = await import('./plugin');
@ -13,3 +15,28 @@ export async function plugin(initializerContext: PluginInitializerContext) {
}
export type { TimelinesPluginUI, TimelinesPluginStart } from './types';
const configSchema = schema.object({
/**
* For internal use. A list of string values (comma delimited) that will enable experimental
* type of functionality that is not yet released. Valid values for this settings need to
* be defined in:
* `x-pack/plugins/timelines/common/experimental_features.ts`
* under the `allowedExperimentalValues` object
*
* @example
* xpack.timelines.enableExperimental:
* - someCrazyFeature
* - someEvenCrazierFeature
*/
enableExperimental: schema.arrayOf(schema.string(), {
defaultValue: () => [],
}),
});
export const config: PluginConfigDescriptor<ConfigSchema> = {
exposeToBrowser: {
enableExperimental: true,
},
schema: configSchema,
};

View file

@ -12,6 +12,8 @@ import { SetupPlugins, StartPlugins, TimelinesPluginUI, TimelinesPluginStart } f
import { timelineSearchStrategyProvider } from './search_strategy/timeline';
import { timelineEqlSearchStrategyProvider } from './search_strategy/timeline/eql';
import { indexFieldsProvider } from './search_strategy/index_fields';
import { parseExperimentalConfigValue } from '../common/experimental_features';
import { ConfigSchema } from './config';
export class TimelinesPlugin
implements Plugin<TimelinesPluginUI, TimelinesPluginStart, SetupPlugins, StartPlugins>
@ -21,6 +23,11 @@ export class TimelinesPlugin
constructor(initializerContext: PluginInitializerContext) {
this.logger = initializerContext.logger.get();
// NOTE: underscored to skip lint warning, but it can be used to implement experimental features behind a flag
const { features: _experimentalFeatures } = parseExperimentalConfigValue(
initializerContext.config.get<ConfigSchema>().enableExperimental
);
}
public setup(core: CoreSetup<StartPlugins, TimelinesPluginStart>, plugins: SetupPlugins) {

View file

@ -17,6 +17,7 @@ import { ENHANCED_ES_SEARCH_STRATEGY } from '@kbn/data-plugin/common';
import { SecurityPluginSetup } from '@kbn/security-plugin/server';
import { Logger } from '@kbn/logging';
import { z } from 'zod';
import { searchStrategyRequestSchema } from '../../../common/api/search_strategy';
import {
TimelineFactoryQueryTypes,
@ -30,7 +31,7 @@ import { isAggCardinalityAggregate } from './factory/helpers/is_agg_cardinality_
export const timelineSearchStrategyProvider = (
data: PluginStart,
logger: Logger,
security?: SecurityPluginSetup
_security?: SecurityPluginSetup
// eslint-disable-next-line @typescript-eslint/no-explicit-any
): ISearchStrategy<z.input<typeof searchStrategyRequestSchema>, any> => {
const es = data.search.getSearchStrategy(ENHANCED_ES_SEARCH_STRATEGY);

View file

@ -37,7 +37,8 @@
"@kbn/search-errors",
"@kbn/search-types",
"@kbn/react-kibana-mount",
"@kbn/field-formats-plugin"
"@kbn/field-formats-plugin",
"@kbn/config-schema"
],
"exclude": [
"target/**/*"