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

[SECURITY SOLUTION] add enableExperimental plugin configuration setting #94944

66 changes: 66 additions & 0 deletions x-pack/plugins/security_solution/common/experimental_features.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* 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 type ExperimentalFeatures = typeof allowedExperimentalValues;

/**
* A list of allowed values that can be used in `xpack.securitySolution.enableExperimental`.
* This object is then used to validate and parse the value entered.
*/
const allowedExperimentalValues = Object.freeze({
fleetServerEnabled: false,
});

type Mutable<T> = { -readonly [P in keyof T]: T[P] };

const SecuritySolutionInvalidExperimentalValueError = class extends Error {};

/**
* A Map of allowed experimental values in uppercase (for data normalization purposes) to an object
* containing internal information about the value (currently only the non-uppercased key).
* Used for validation of values entered via the plugin config setting.
*/
const allowedKeys = (Object.keys(allowedExperimentalValues) as Array<
keyof ExperimentalFeatures
>).reduce((map, key) => {
map.set(key.toUpperCase(), { key });
return map;
}, new Map<string, { key: keyof ExperimentalFeatures }>());

/**
* Parses the string value used in `xpack.securitySolution.enableExperimental` kibana configuration,
* which should be a string of values delimited by a comma (`,`)
paul-tavares marked this conversation as resolved.
Show resolved Hide resolved
*
* @param configValue
* @throws SecuritySolutionInvalidExperimentalValue
*/
export const parseExperimentalConfigValue = (configValue: string): ExperimentalFeatures => {
const stringValues = configValue
.split(/,/)
.filter(Boolean)
dasansol92 marked this conversation as resolved.
Show resolved Hide resolved
.map((value) => value.trim());
dasansol92 marked this conversation as resolved.
Show resolved Hide resolved
const enabledFeatures: Mutable<Partial<ExperimentalFeatures>> = {};

for (const value of stringValues) {
const allowedKey = allowedKeys.get(value.toUpperCase());

if (!allowedKey) {
throw new SecuritySolutionInvalidExperimentalValueError(
`[${value}] is not a valid value for 'xpack.securitySolution.enableExperimental'. Valid values are: ${Object.keys(
allowedExperimentalValues
).join(', ')}`
);
} else {
enabledFeatures[allowedKey.key] = true;
}
}

return {
...allowedExperimentalValues,
...enabledFeatures,
};
};
23 changes: 21 additions & 2 deletions x-pack/plugins/security_solution/server/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import { schema, TypeOf } from '@kbn/config-schema';
import { PluginInitializerContext } from '../../../../src/core/server';
import { SIGNALS_INDEX_KEY, DEFAULT_SIGNALS_INDEX } from '../common/constants';
import { parseExperimentalConfigValue } from '../common/experimental_features';

export const configSchema = schema.object({
enabled: schema.boolean({ defaultValue: true }),
Expand All @@ -17,8 +18,26 @@ export const configSchema = schema.object({
maxTimelineImportPayloadBytes: schema.number({ defaultValue: 10485760 }),
[SIGNALS_INDEX_KEY]: schema.string({ defaultValue: DEFAULT_SIGNALS_INDEX }),

/** Fleet server integration */
fleetServerEnabled: schema.boolean({ defaultValue: false }),
/**
* 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/security_solution/common/experimental_features.ts`
* under the `allowedExperimentalValues` object
*
* @example
* xpack.securitySolution.enableExperimental: "fleetServerEnabled, trustedAppsByPolicyEnabled"
*/
enableExperimental: schema.string({
defaultValue: '',
validate(value) {
try {
parseExperimentalConfigValue(value);
} catch (e) {
return e.message;
}
},
}),

/**
* Host Endpoint Configuration
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const createMockConfig = (): ConfigType => ({
maxRuleImportPayloadBytes: 10485760,
maxTimelineImportExportSize: 10000,
maxTimelineImportPayloadBytes: 10485760,
fleetServerEnabled: true,
enableExperimental: '',
endpointResultListDefaultFirstPageIndex: 0,
endpointResultListDefaultPageSize: 10,
alertResultListDefaultDateRange: {
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/security_solution/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ import {
import { licenseService } from './lib/license/license';
import { PolicyWatcher } from './endpoint/lib/policy/license_watch';
import { securitySolutionTimelineEqlSearchStrategyProvider } from './search_strategy/timeline/eql';
import { parseExperimentalConfigValue } from '../common/experimental_features';

export interface SetupPlugins {
alerting: AlertingSetup;
Expand Down Expand Up @@ -357,7 +358,7 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
logger: this.logger,
cache: this.artifactsCache,
},
this.config.fleetServerEnabled
parseExperimentalConfigValue(this.config.enableExperimental).fleetServerEnabled
);

if (this.manifestTask) {
Expand Down