Skip to content

Commit aa18a46

Browse files
authored
[Security Solution][Endpoint] Saved object and Index template definitions for Elastic Defend scripts library (#243424)
## Summary - PR adds saved objects and index template definitions in support of Elastic Defend support for a Scripts Library - No logic uses these data storage definitions yet - The new saved object type will be used to store information about the scripts that user can upload and store - The index templates will be used to store the actual content of the script files that will be uploaded (using the `Files` plugins) - They are currently hidden behind feature flag `responseActionsScriptLibraryManagement`
1 parent b11371b commit aa18a46

File tree

11 files changed

+283
-4
lines changed

11 files changed

+283
-4
lines changed

x-pack/solutions/security/plugins/security_solution/common/experimental_features.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ export const allowedExperimentalValues = Object.freeze({
4949
*/
5050
responseActionsEndpointMemoryDump: false,
5151

52+
/**
53+
* Scripts library in support of `runscript`/upload-execute` new command for elastic defend
54+
* Release: 9.4
55+
*/
56+
responseActionsScriptLibraryManagement: false,
57+
5258
/**
5359
* Enables the Assistant Model Evaluation advanced setting and API endpoint, introduced in `8.11.0`.
5460
*/

x-pack/solutions/security/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import type { PluginStartContract as ActionsPluginStartContract } from '@kbn/act
2828
import type { Space } from '@kbn/spaces-plugin/common';
2929
import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common';
3030
import type { SpacesServiceStart } from '@kbn/spaces-plugin/server';
31+
import { installScriptsLibraryIndexTemplates } from './lib/scripts_library';
3132
import type { ReferenceDataClientInterface } from './lib/reference_data';
3233
import { ReferenceDataClient } from './lib/reference_data';
3334
import type { TelemetryConfigProvider } from '../../common/telemetry_config/telemetry_config_provider';
@@ -132,6 +133,17 @@ export class EndpointAppContextService {
132133

133134
this.registerFleetExtensions();
134135
this.registerListsExtensions();
136+
137+
// Setup scripts library
138+
if (this.startDependencies.experimentalFeatures.responseActionsScriptLibraryManagement) {
139+
const scriptsLogger = this.createLogger('scriptsLibrarySetup');
140+
installScriptsLibraryIndexTemplates({
141+
esClient: this.getInternalEsClient(),
142+
logger: scriptsLogger,
143+
}).catch((e) => {
144+
scriptsLogger.error(e);
145+
});
146+
}
135147
}
136148

137149
public stop() {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
const SCRIPTS_LIBRARY_FILE_INDEX_NAME_PREFIX = '.endpoint-script-file';
9+
10+
export const SCRIPTS_LIBRARY_FILE_METADATA_INDEX_NAME_PREFIX = `${SCRIPTS_LIBRARY_FILE_INDEX_NAME_PREFIX}-meta`;
11+
export const SCRIPTS_LIBRARY_FILE_DATA_INDEX_NAME_PREFIX = `${SCRIPTS_LIBRARY_FILE_INDEX_NAME_PREFIX}-data`;
12+
13+
export const SCRIPTS_LIBRARY_FILE_METADATA_INDEX_NAME = `${SCRIPTS_LIBRARY_FILE_METADATA_INDEX_NAME_PREFIX}-default`;
14+
export const SCRIPTS_LIBRARY_FILE_DATA_INDEX_NAME = `${SCRIPTS_LIBRARY_FILE_DATA_INDEX_NAME_PREFIX}-default`;
15+
16+
export const SCRIPTS_LIBRARY_SAVED_OBJECT_TYPE = 'security:endpoint-scripts-library';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
export { installScriptsLibraryIndexTemplates } from './install';
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { IndicesPutIndexTemplateRequest } from '@elastic/elasticsearch/lib/api/types';
9+
import { deepFreeze } from '@kbn/std';
10+
import {
11+
SCRIPTS_LIBRARY_FILE_DATA_INDEX_NAME_PREFIX,
12+
SCRIPTS_LIBRARY_FILE_METADATA_INDEX_NAME_PREFIX,
13+
} from '../constants';
14+
15+
/**
16+
* Index template for storing File metadata. Index is used mainly with the Files plugin
17+
* to manage files associated with Elastic Defend Scripts library entries
18+
*/
19+
export const ScriptsFileMetadataIndexTemplate = deepFreeze<IndicesPutIndexTemplateRequest>({
20+
name: SCRIPTS_LIBRARY_FILE_METADATA_INDEX_NAME_PREFIX,
21+
index_patterns: [`${SCRIPTS_LIBRARY_FILE_METADATA_INDEX_NAME_PREFIX}-*`],
22+
priority: 500,
23+
allow_auto_create: true,
24+
_meta: {
25+
description: 'Index template for Elastic Defend scripts library storage of file metadata',
26+
managed: true,
27+
},
28+
template: {
29+
settings: {
30+
'index.auto_expand_replicas': '0-1',
31+
'index.hidden': true,
32+
},
33+
mappings: {
34+
dynamic: false,
35+
properties: {
36+
file: {
37+
properties: {
38+
Status: { type: 'keyword' },
39+
ChunkSize: { type: 'integer' },
40+
Compression: { type: 'keyword' },
41+
name: { type: 'keyword' },
42+
Meta: {
43+
properties: {
44+
script_id: { type: 'keyword' },
45+
},
46+
},
47+
},
48+
},
49+
},
50+
},
51+
},
52+
}) as IndicesPutIndexTemplateRequest;
53+
54+
/**
55+
* Index template for storing File data content. Index is used mainly with the Files plugin
56+
* to manage files associated with Elastic Defend Scripts library entries
57+
*/
58+
export const ScriptsFileDataIndexTemplate = deepFreeze<IndicesPutIndexTemplateRequest>({
59+
name: SCRIPTS_LIBRARY_FILE_DATA_INDEX_NAME_PREFIX,
60+
index_patterns: [`${SCRIPTS_LIBRARY_FILE_DATA_INDEX_NAME_PREFIX}-*`],
61+
priority: 500,
62+
allow_auto_create: true,
63+
_meta: {
64+
description: 'Index template for Elastic Defend scripts library storage of file data content',
65+
managed: true,
66+
},
67+
template: {
68+
settings: {
69+
'index.auto_expand_replicas': '0-1',
70+
'index.hidden': true,
71+
},
72+
mappings: {
73+
dynamic: false,
74+
properties: {
75+
data: {
76+
type: 'binary',
77+
store: true,
78+
},
79+
bid: {
80+
type: 'keyword',
81+
},
82+
sha2: {
83+
type: 'keyword',
84+
index: false,
85+
},
86+
last: {
87+
type: 'boolean',
88+
index: false,
89+
},
90+
},
91+
},
92+
},
93+
}) as IndicesPutIndexTemplateRequest;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { ElasticsearchClient, Logger } from '@kbn/core/server';
9+
import { ScriptsFileDataIndexTemplate, ScriptsFileMetadataIndexTemplate } from './index_template';
10+
import { catchAndWrapError } from '../../../utils';
11+
12+
interface InstallScriptsLibraryIndexTemplatesOptions {
13+
esClient: ElasticsearchClient;
14+
logger: Logger;
15+
}
16+
17+
export const installScriptsLibraryIndexTemplates = async ({
18+
esClient,
19+
logger,
20+
}: InstallScriptsLibraryIndexTemplatesOptions): Promise<void> => {
21+
logger.debug('Installing/updating scripts library ES index templates');
22+
23+
await esClient.indices
24+
.putIndexTemplate(ScriptsFileMetadataIndexTemplate)
25+
.catch(catchAndWrapError);
26+
27+
await esClient.indices.putIndexTemplate(ScriptsFileDataIndexTemplate).catch(catchAndWrapError);
28+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
export * from './es_assets';
9+
export * from './saved_objects';
10+
export * from './constants';
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
export * from './mappings';
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0; you may not use this file except in compliance with the Elastic License
5+
* 2.0.
6+
*/
7+
8+
import type { SavedObjectsType } from '@kbn/core-saved-objects-server';
9+
import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
10+
import { schema } from '@kbn/config-schema';
11+
import { SCRIPTS_LIBRARY_SAVED_OBJECT_TYPE } from '../constants';
12+
13+
const ScriptsLibraryAttributesSchemaV1 = schema.object({
14+
id: schema.string(),
15+
name: schema.string(),
16+
platform: schema.string(),
17+
hash: schema.maybe(schema.string()),
18+
requires_input: schema.maybe(schema.boolean()),
19+
description: schema.maybe(schema.string()),
20+
instructions: schema.maybe(schema.string()),
21+
example: schema.maybe(schema.string()),
22+
executable: schema.maybe(
23+
schema.object({
24+
linux: schema.maybe(schema.string()),
25+
macos: schema.maybe(schema.string()),
26+
windows: schema.maybe(schema.string()),
27+
})
28+
),
29+
created_by: schema.string(),
30+
updated_by: schema.string(),
31+
});
32+
33+
export const scriptsLibrarySavedObjectType: SavedObjectsType = {
34+
name: SCRIPTS_LIBRARY_SAVED_OBJECT_TYPE,
35+
indexPattern: SECURITY_SOLUTION_SAVED_OBJECT_INDEX,
36+
namespaceType: 'multiple',
37+
hidden: true,
38+
mappings: {
39+
dynamic: false,
40+
properties: {
41+
id: { type: 'keyword' },
42+
name: { type: 'keyword' },
43+
platform: { type: 'keyword' },
44+
hash: { type: 'keyword' },
45+
requires_input: { type: 'boolean' },
46+
description: { type: 'keyword' },
47+
instructions: { type: 'keyword' },
48+
example: { type: 'keyword' },
49+
executable: {
50+
properties: {
51+
linux: { type: 'keyword' },
52+
macos: { type: 'keyword' },
53+
windows: { type: 'keyword' },
54+
},
55+
},
56+
created_by: { type: 'keyword' },
57+
updated_by: { type: 'keyword' },
58+
// FYI: the created_at/_by fields are auto populated by the so framework
59+
},
60+
},
61+
modelVersions: {
62+
1: {
63+
changes: [],
64+
schemas: {
65+
forwardCompatibility: ScriptsLibraryAttributesSchemaV1.extends({}, { unknowns: 'ignore' }),
66+
create: ScriptsLibraryAttributesSchemaV1,
67+
},
68+
},
69+
},
70+
};

x-pack/solutions/security/plugins/security_solution/server/plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ export class Plugin implements ISecuritySolutionPlugin {
234234
const { appClientFactory, productFeaturesService, pluginContext, config, logger } = this;
235235
const experimentalFeatures = config.experimentalFeatures;
236236

237-
initSavedObjects(core.savedObjects);
237+
initSavedObjects(core.savedObjects, experimentalFeatures, this.logger.get('initSavedObjects'));
238238
initEncryptedSavedObjects({
239239
encryptedSavedObjects: plugins.encryptedSavedObjects,
240240
logger: this.logger,

0 commit comments

Comments
 (0)