From eb6df37c701ff91fb3156f9265e42d1afe0d0ffe Mon Sep 17 00:00:00 2001 From: Paul Tavares <56442535+paul-tavares@users.noreply.github.com> Date: Mon, 22 Mar 2021 14:09:24 -0400 Subject: [PATCH] [SECURITY SOLUTION] add `enableExperimental` plugin configuration setting (#94944) (#95071) * Added new setting (enableExperimental) to plugin configuration * Remove plugin config setting `fleetServerEnabled` and use instead `enableExperimental` --- .../common/experimental_features.ts | 52 +++++++++++++++++++ .../security_solution/server/config.ts | 32 +++++++++++- .../routes/__mocks__/index.ts | 2 +- .../security_solution/server/plugin.ts | 3 +- 4 files changed, 85 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/security_solution/common/experimental_features.ts diff --git a/x-pack/plugins/security_solution/common/experimental_features.ts b/x-pack/plugins/security_solution/common/experimental_features.ts new file mode 100644 index 000000000000..c764c31a2d78 --- /dev/null +++ b/x-pack/plugins/security_solution/common/experimental_features.ts @@ -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. + */ + +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 ExperimentalConfigKeys = Array; +type Mutable = { -readonly [P in keyof T]: T[P] }; + +const SecuritySolutionInvalidExperimentalValue = class extends Error {}; +const allowedKeys = Object.keys(allowedExperimentalValues) as Readonly; + +/** + * Parses the string value used in `xpack.securitySolution.enableExperimental` kibana configuration, + * which should be a string of values delimited by a comma (`,`) + * + * @param configValue + * @throws SecuritySolutionInvalidExperimentalValue + */ +export const parseExperimentalConfigValue = (configValue: string[]): ExperimentalFeatures => { + const enabledFeatures: Mutable> = {}; + + for (const value of configValue) { + if (!isValidExperimentalValue(value)) { + throw new SecuritySolutionInvalidExperimentalValue(`[${value}] is not valid.`); + } + + enabledFeatures[value as keyof ExperimentalFeatures] = true; + } + + return { + ...allowedExperimentalValues, + ...enabledFeatures, + }; +}; + +export const isValidExperimentalValue = (value: string): boolean => { + return allowedKeys.includes(value as keyof ExperimentalFeatures); +}; + +export const getExperimentalAllowedValues = (): string[] => [...allowedKeys]; diff --git a/x-pack/plugins/security_solution/server/config.ts b/x-pack/plugins/security_solution/server/config.ts index b2d54df80e06..88d57a47b6c4 100644 --- a/x-pack/plugins/security_solution/server/config.ts +++ b/x-pack/plugins/security_solution/server/config.ts @@ -8,6 +8,12 @@ import { schema, TypeOf } from '@kbn/config-schema'; import { PluginInitializerContext } from '../../../../src/core/server'; import { SIGNALS_INDEX_KEY, DEFAULT_SIGNALS_INDEX } from '../common/constants'; +import { + getExperimentalAllowedValues, + isValidExperimentalValue, +} from '../common/experimental_features'; + +const allowedExperimentalValues = getExperimentalAllowedValues(); export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: true }), @@ -17,8 +23,30 @@ 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.arrayOf(schema.string(), { + defaultValue: () => [], + validate(list) { + for (const key of list) { + if (!isValidExperimentalValue(key)) { + return `[${key}] is not allowed. Allowed values are: ${allowedExperimentalValues.join( + ', ' + )}`; + } + } + }, + }), /** * Host Endpoint Configuration diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/index.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/index.ts index 31e1d9c2699c..2e72ac137adc 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/index.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/index.ts @@ -21,7 +21,7 @@ export const createMockConfig = (): ConfigType => ({ maxRuleImportPayloadBytes: 10485760, maxTimelineImportExportSize: 10000, maxTimelineImportPayloadBytes: 10485760, - fleetServerEnabled: true, + enableExperimental: [], endpointResultListDefaultFirstPageIndex: 0, endpointResultListDefaultPageSize: 10, alertResultListDefaultDateRange: { diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 5ce102995156..43096805544a 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -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; @@ -357,7 +358,7 @@ export class Plugin implements IPlugin