mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Endpoint][EPM] Retrieve Index Pattern from Ingest Manager (#63016)
* Endpoint successfully depending on ingest manager to initialize * Moving the endpoint functional tests to their own directory to avoid enabling ingest in the base tests * Removing page objects and other endpoint fields from base functional * Updating code owners with new functional location * Adding index pattern functionality * Missed a file * Pointing resolver tests at endpoint functional tests * Pointing space tests at the endpoint functional directory * Adding ingest service to do setup and tests for 500s * Correcting services path * Adding jest test names * Updating es archives with the correct mapping and index names * Fixing import error * Adding resolver tests to code owners * enabling epm flag for functional tests * adding correct tag to test * Removing the version information and unneeded xsrf * Addressing endpoint index pattern feedback * Removing unused import * Renaming index pattern to es index pattern * Fixing missed index pattern calls * Removing unused import * Fixing type error * Moving es_index_pattern outside of installed and fixing function name * Keeping the event index the same for now * Wrapping index pattern await in try catch * Address PR feedback, adding comments
This commit is contained in:
parent
cae0c964ac
commit
0a9e17b57f
55 changed files with 962 additions and 464 deletions
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
|
@ -209,9 +209,12 @@
|
|||
# Endpoint
|
||||
/x-pack/plugins/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/api_integration/apis/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/endpoint_api_integration_no_ingest/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional_endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional_endpoint_ingest_failure/ @elastic/endpoint-app-team
|
||||
/x-pack/test/functional/es_archives/endpoint/ @elastic/endpoint-app-team
|
||||
/x-pack/test/plugin_functional/plugins/resolver_test/ @elastic/endpoint-app-team
|
||||
/x-pack/test/plugin_functional/test_suites/resolver/ @elastic/endpoint-app-team
|
||||
|
||||
# SIEM
|
||||
/x-pack/legacy/plugins/siem/ @elastic/siem
|
||||
|
|
9
x-pack/plugins/endpoint/common/schema/index_pattern.ts
Normal file
9
x-pack/plugins/endpoint/common/schema/index_pattern.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
export const indexPatternGetParamsSchema = schema.object({ datasetPath: schema.string() });
|
|
@ -7,6 +7,7 @@
|
|||
import { SearchResponse } from 'elasticsearch';
|
||||
import { TypeOf } from '@kbn/config-schema';
|
||||
import { alertingIndexGetQuerySchema } from './schema/alert_index';
|
||||
import { indexPatternGetParamsSchema } from './schema/index_pattern';
|
||||
import { Datasource, NewDatasource } from '../../ingest_manager/common';
|
||||
|
||||
/**
|
||||
|
@ -33,9 +34,9 @@ export type Direction = 'asc' | 'desc';
|
|||
|
||||
export class EndpointAppConstants {
|
||||
static BASE_API_URL = '/api/endpoint';
|
||||
static ENDPOINT_INDEX_NAME = 'endpoint-agent*';
|
||||
static INDEX_PATTERN_ROUTE = `${EndpointAppConstants.BASE_API_URL}/index_pattern`;
|
||||
static ALERT_INDEX_NAME = 'events-endpoint-1';
|
||||
static EVENT_INDEX_NAME = 'events-endpoint-*';
|
||||
static EVENT_DATASET = 'events';
|
||||
static DEFAULT_TOTAL_HITS = 10000;
|
||||
/**
|
||||
* Legacy events are stored in indices with endgame-* prefix
|
||||
|
@ -446,6 +447,11 @@ export type AlertingIndexGetQueryInput = KbnConfigSchemaInputTypeOf<
|
|||
*/
|
||||
export type AlertingIndexGetQueryResult = TypeOf<typeof alertingIndexGetQuerySchema>;
|
||||
|
||||
/**
|
||||
* Result of the validated params when handling an index pattern request.
|
||||
*/
|
||||
export type IndexPatternGetParamsResult = TypeOf<typeof indexPatternGetParamsSchema>;
|
||||
|
||||
/**
|
||||
* Endpoint Policy configuration
|
||||
*/
|
||||
|
|
|
@ -15,10 +15,14 @@ import { EndpointAppConstants } from '../../../../../common/types';
|
|||
export const alertMiddlewareFactory: MiddlewareFactory<AlertListState> = (coreStart, depsStart) => {
|
||||
async function fetchIndexPatterns(): Promise<IIndexPattern[]> {
|
||||
const { indexPatterns } = depsStart.data;
|
||||
const indexName = EndpointAppConstants.ALERT_INDEX_NAME;
|
||||
const fields = await indexPatterns.getFieldsForWildcard({ pattern: indexName });
|
||||
const eventsPattern: { indexPattern: string } = await coreStart.http.get(
|
||||
`${EndpointAppConstants.INDEX_PATTERN_ROUTE}/${EndpointAppConstants.EVENT_DATASET}`
|
||||
);
|
||||
const fields = await indexPatterns.getFieldsForWildcard({
|
||||
pattern: eventsPattern.indexPattern,
|
||||
});
|
||||
const indexPattern: IIndexPattern = {
|
||||
title: indexName,
|
||||
title: eventsPattern.indexPattern,
|
||||
fields,
|
||||
};
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ async function main() {
|
|||
metadataIndex: {
|
||||
alias: 'mi',
|
||||
describe: 'index to store host metadata in',
|
||||
default: 'endpoint-agent-1',
|
||||
default: 'metrics-endpoint-default-1',
|
||||
type: 'string',
|
||||
},
|
||||
auth: {
|
||||
|
|
77
x-pack/plugins/endpoint/server/index_pattern.ts
Normal file
77
x-pack/plugins/endpoint/server/index_pattern.ts
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { Logger, LoggerFactory, RequestHandlerContext } from 'kibana/server';
|
||||
import { ESIndexPatternService } from '../../ingest_manager/server';
|
||||
import { EndpointAppConstants } from '../common/types';
|
||||
|
||||
export interface IndexPatternRetriever {
|
||||
getIndexPattern(ctx: RequestHandlerContext, datasetPath: string): Promise<string>;
|
||||
getEventIndexPattern(ctx: RequestHandlerContext): Promise<string>;
|
||||
getMetadataIndexPattern(ctx: RequestHandlerContext): Promise<string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to retrieve an index pattern. It should be used in the server side code whenever
|
||||
* an index pattern is needed to query data within ES. The index pattern is constructed by the Ingest Manager
|
||||
* based on the contents of the Endpoint Package in the Package Registry.
|
||||
*/
|
||||
export class IngestIndexPatternRetriever implements IndexPatternRetriever {
|
||||
private static endpointPackageName = 'endpoint';
|
||||
private static metadataDataset = 'metadata';
|
||||
private readonly log: Logger;
|
||||
constructor(private readonly service: ESIndexPatternService, loggerFactory: LoggerFactory) {
|
||||
this.log = loggerFactory.get('index-pattern-retriever');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the index pattern for querying events within elasticsearch.
|
||||
*
|
||||
* @param ctx a RequestHandlerContext from a route handler
|
||||
* @returns a string representing the index pattern (e.g. `events-endpoint-*`)
|
||||
*/
|
||||
async getEventIndexPattern(ctx: RequestHandlerContext) {
|
||||
return await this.getIndexPattern(ctx, EndpointAppConstants.EVENT_DATASET);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the index pattern for querying endpoint metadata within elasticsearch.
|
||||
*
|
||||
* @param ctx a RequestHandlerContext from a route handler
|
||||
* @returns a string representing the index pattern (e.g. `metrics-endpoint-*`)
|
||||
*/
|
||||
async getMetadataIndexPattern(ctx: RequestHandlerContext) {
|
||||
return await this.getIndexPattern(ctx, IngestIndexPatternRetriever.metadataDataset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the index pattern for a specific dataset for querying endpoint data.
|
||||
*
|
||||
* @param ctx a RequestHandlerContext from a route handler
|
||||
* @param datasetPath a string of the path being used for a dataset within the Endpoint Package
|
||||
* (e.g. `events`, `metadata`)
|
||||
* @returns a string representing the index pattern (e.g. `metrics-endpoint-*`)
|
||||
*/
|
||||
async getIndexPattern(ctx: RequestHandlerContext, datasetPath: string) {
|
||||
try {
|
||||
const pattern = await this.service.getESIndexPattern(
|
||||
ctx.core.savedObjects.client,
|
||||
IngestIndexPatternRetriever.endpointPackageName,
|
||||
datasetPath
|
||||
);
|
||||
|
||||
if (!pattern) {
|
||||
const msg = `Unable to retrieve the index pattern for dataset: ${datasetPath}`;
|
||||
this.log.warn(msg);
|
||||
throw new Error(msg);
|
||||
}
|
||||
return pattern;
|
||||
} catch (error) {
|
||||
const errMsg = `Error occurred while retrieving pattern for: ${datasetPath} error: ${error}`;
|
||||
this.log.warn(errMsg);
|
||||
throw new Error(errMsg);
|
||||
}
|
||||
}
|
||||
}
|
44
x-pack/plugins/endpoint/server/mocks.ts
Normal file
44
x-pack/plugins/endpoint/server/mocks.ts
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a mock IndexPatternRetriever for use in tests.
|
||||
*
|
||||
* @param indexPattern a string index pattern to return when any of the mock's public methods are called.
|
||||
* @returns the same string passed in via `indexPattern`
|
||||
*/
|
||||
export const createMockIndexPatternRetriever = (indexPattern: string) => {
|
||||
const mockGetFunc = jest.fn().mockResolvedValue(indexPattern);
|
||||
return {
|
||||
getIndexPattern: mockGetFunc,
|
||||
getEventIndexPattern: mockGetFunc,
|
||||
getMetadataIndexPattern: mockGetFunc,
|
||||
};
|
||||
};
|
||||
|
||||
export const MetadataIndexPattern = 'metrics-endpoint-*';
|
||||
|
||||
/**
|
||||
* Creates a mock IndexPatternRetriever for use in tests that returns `metrics-endpoint-*`
|
||||
*/
|
||||
export const createMockMetadataIndexPatternRetriever = () => {
|
||||
return createMockIndexPatternRetriever(MetadataIndexPattern);
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a mock IndexPatternService for use in tests that need to interact with the Ingest Manager's
|
||||
* ESIndexPatternService.
|
||||
*
|
||||
* @param indexPattern a string index pattern to return when called by a test
|
||||
* @returns the same value as `indexPattern` parameter
|
||||
*/
|
||||
export const createMockIndexPatternService = (indexPattern: string) => {
|
||||
return {
|
||||
esIndexPatternService: {
|
||||
getESIndexPattern: jest.fn().mockResolvedValue(indexPattern),
|
||||
},
|
||||
};
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
import { EndpointPlugin, EndpointPluginSetupDependencies } from './plugin';
|
||||
import { coreMock } from '../../../../src/core/server/mocks';
|
||||
import { PluginSetupContract } from '../../features/server';
|
||||
import { createMockIndexPatternService } from './mocks';
|
||||
|
||||
describe('test endpoint plugin', () => {
|
||||
let plugin: EndpointPlugin;
|
||||
|
@ -28,7 +29,10 @@ describe('test endpoint plugin', () => {
|
|||
getFeaturesUICapabilities: jest.fn(),
|
||||
registerLegacyAPI: jest.fn(),
|
||||
};
|
||||
mockedEndpointPluginSetupDependencies = { features: mockedPluginSetupContract };
|
||||
mockedEndpointPluginSetupDependencies = {
|
||||
features: mockedPluginSetupContract,
|
||||
ingestManager: createMockIndexPatternService(''),
|
||||
};
|
||||
});
|
||||
|
||||
it('test properly setup plugin', async () => {
|
||||
|
|
|
@ -6,12 +6,15 @@
|
|||
import { Plugin, CoreSetup, PluginInitializerContext, Logger } from 'kibana/server';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { PluginSetupContract as FeaturesPluginSetupContract } from '../../features/server';
|
||||
import { IngestManagerSetupContract } from '../../ingest_manager/server';
|
||||
import { createConfig$, EndpointConfigType } from './config';
|
||||
import { EndpointAppContext } from './types';
|
||||
|
||||
import { registerAlertRoutes } from './routes/alerts';
|
||||
import { registerResolverRoutes } from './routes/resolver';
|
||||
import { registerIndexPatternRoute } from './routes/index_pattern';
|
||||
import { registerEndpointRoutes } from './routes/metadata';
|
||||
import { IngestIndexPatternRetriever } from './index_pattern';
|
||||
|
||||
export type EndpointPluginStart = void;
|
||||
export type EndpointPluginSetup = void;
|
||||
|
@ -19,6 +22,7 @@ export interface EndpointPluginStartDependencies {} // eslint-disable-line @type
|
|||
|
||||
export interface EndpointPluginSetupDependencies {
|
||||
features: FeaturesPluginSetupContract;
|
||||
ingestManager: IngestManagerSetupContract;
|
||||
}
|
||||
|
||||
export class EndpointPlugin
|
||||
|
@ -62,6 +66,10 @@ export class EndpointPlugin
|
|||
},
|
||||
});
|
||||
const endpointContext = {
|
||||
indexPatternRetriever: new IngestIndexPatternRetriever(
|
||||
plugins.ingestManager.esIndexPatternService,
|
||||
this.initializerContext.logger
|
||||
),
|
||||
logFactory: this.initializerContext.logger,
|
||||
config: (): Promise<EndpointConfigType> => {
|
||||
return createConfig$(this.initializerContext)
|
||||
|
@ -73,6 +81,7 @@ export class EndpointPlugin
|
|||
registerEndpointRoutes(router, endpointContext);
|
||||
registerResolverRoutes(router, endpointContext);
|
||||
registerAlertRoutes(router, endpointContext);
|
||||
registerIndexPatternRoute(router, endpointContext);
|
||||
}
|
||||
|
||||
public start() {
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
import { registerAlertRoutes } from './index';
|
||||
import { EndpointConfigSchema } from '../../config';
|
||||
import { alertingIndexGetQuerySchema } from '../../../common/schema/alert_index';
|
||||
import { createMockIndexPatternRetriever } from '../../mocks';
|
||||
|
||||
describe('test alerts route', () => {
|
||||
let routerMock: jest.Mocked<IRouter>;
|
||||
|
@ -24,6 +25,7 @@ describe('test alerts route', () => {
|
|||
mockClusterClient.asScoped.mockReturnValue(mockScopedClient);
|
||||
routerMock = httpServiceMock.createRouter();
|
||||
registerAlertRoutes(routerMock, {
|
||||
indexPatternRetriever: createMockIndexPatternRetriever('events-endpoint-*'),
|
||||
logFactory: loggingServiceMock.create(),
|
||||
config: () => Promise.resolve(EndpointConfigSchema.validate({})),
|
||||
});
|
||||
|
|
|
@ -26,15 +26,18 @@ export const alertDetailsHandlerWrapper = function(
|
|||
id: alertId,
|
||||
})) as GetResponse<AlertEvent>;
|
||||
|
||||
const indexPattern = await endpointAppContext.indexPatternRetriever.getEventIndexPattern(ctx);
|
||||
|
||||
const config = await endpointAppContext.config();
|
||||
const pagination: AlertDetailsPagination = new AlertDetailsPagination(
|
||||
config,
|
||||
ctx,
|
||||
req.params,
|
||||
response
|
||||
response,
|
||||
indexPattern
|
||||
);
|
||||
|
||||
const currentHostInfo = await getHostData(ctx, response._source.host.id);
|
||||
const currentHostInfo = await getHostData(ctx, response._source.host.id, indexPattern);
|
||||
|
||||
return res.ok({
|
||||
body: {
|
||||
|
|
|
@ -29,7 +29,8 @@ export class AlertDetailsPagination extends Pagination<
|
|||
config: EndpointConfigType,
|
||||
requestContext: RequestHandlerContext,
|
||||
state: AlertDetailsRequestParams,
|
||||
data: GetResponse<AlertEvent>
|
||||
data: GetResponse<AlertEvent>,
|
||||
private readonly indexPattern: string
|
||||
) {
|
||||
super(config, requestContext, state, data);
|
||||
}
|
||||
|
@ -54,7 +55,8 @@ export class AlertDetailsPagination extends Pagination<
|
|||
|
||||
const response = await searchESForAlerts(
|
||||
this.requestContext.core.elasticsearch.dataClient,
|
||||
reqData
|
||||
reqData,
|
||||
this.indexPattern
|
||||
);
|
||||
return response;
|
||||
}
|
||||
|
|
|
@ -97,7 +97,8 @@ function buildSort(query: AlertSearchQuery): AlertSort {
|
|||
* Builds a request body for Elasticsearch, given a set of query params.
|
||||
**/
|
||||
const buildAlertSearchQuery = async (
|
||||
query: AlertSearchQuery
|
||||
query: AlertSearchQuery,
|
||||
indexPattern: string
|
||||
): Promise<AlertSearchRequestWrapper> => {
|
||||
let totalHitsMin: number = EndpointAppConstants.DEFAULT_TOTAL_HITS;
|
||||
|
||||
|
@ -125,7 +126,7 @@ const buildAlertSearchQuery = async (
|
|||
|
||||
const reqWrapper: AlertSearchRequestWrapper = {
|
||||
size: query.pageSize,
|
||||
index: EndpointAppConstants.ALERT_INDEX_NAME,
|
||||
index: indexPattern,
|
||||
body: reqBody,
|
||||
};
|
||||
|
||||
|
@ -141,9 +142,10 @@ const buildAlertSearchQuery = async (
|
|||
**/
|
||||
export const searchESForAlerts = async (
|
||||
dataClient: IScopedClusterClient,
|
||||
query: AlertSearchQuery
|
||||
query: AlertSearchQuery,
|
||||
indexPattern: string
|
||||
): Promise<SearchResponse<AlertEvent>> => {
|
||||
const reqWrapper = await buildAlertSearchQuery(query);
|
||||
const reqWrapper = await buildAlertSearchQuery(query, indexPattern);
|
||||
const response = (await dataClient.callAsCurrentUser('search', reqWrapper)) as SearchResponse<
|
||||
AlertEvent
|
||||
>;
|
||||
|
|
|
@ -18,8 +18,13 @@ export const alertListHandlerWrapper = function(
|
|||
res
|
||||
) => {
|
||||
try {
|
||||
const indexPattern = await endpointAppContext.indexPatternRetriever.getEventIndexPattern(ctx);
|
||||
const reqData = await getRequestData(req, endpointAppContext);
|
||||
const response = await searchESForAlerts(ctx.core.elasticsearch.dataClient, reqData);
|
||||
const response = await searchESForAlerts(
|
||||
ctx.core.elasticsearch.dataClient,
|
||||
reqData,
|
||||
indexPattern
|
||||
);
|
||||
const mappedBody = await mapToAlertResultList(ctx, endpointAppContext, reqData, response);
|
||||
return res.ok({ body: mappedBody });
|
||||
} catch (err) {
|
||||
|
|
42
x-pack/plugins/endpoint/server/routes/index_pattern.ts
Normal file
42
x-pack/plugins/endpoint/server/routes/index_pattern.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { IRouter, Logger, RequestHandler } from 'kibana/server';
|
||||
import { EndpointAppContext } from '../types';
|
||||
import { IndexPatternGetParamsResult, EndpointAppConstants } from '../../common/types';
|
||||
import { indexPatternGetParamsSchema } from '../../common/schema/index_pattern';
|
||||
import { IndexPatternRetriever } from '../index_pattern';
|
||||
|
||||
function handleIndexPattern(
|
||||
log: Logger,
|
||||
indexRetriever: IndexPatternRetriever
|
||||
): RequestHandler<IndexPatternGetParamsResult> {
|
||||
return async (context, req, res) => {
|
||||
try {
|
||||
return res.ok({
|
||||
body: {
|
||||
indexPattern: await indexRetriever.getIndexPattern(context, req.params.datasetPath),
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
log.warn(error);
|
||||
return res.notFound({ body: error });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export function registerIndexPatternRoute(router: IRouter, endpointAppContext: EndpointAppContext) {
|
||||
const log = endpointAppContext.logFactory.get('index_pattern');
|
||||
|
||||
router.get(
|
||||
{
|
||||
path: `${EndpointAppConstants.INDEX_PATTERN_ROUTE}/{datasetPath}`,
|
||||
validate: { params: indexPatternGetParamsSchema },
|
||||
options: { authRequired: true },
|
||||
},
|
||||
handleIndexPattern(log, endpointAppContext.indexPatternRetriever)
|
||||
);
|
||||
}
|
|
@ -8,9 +8,9 @@ import { IRouter, RequestHandlerContext } from 'kibana/server';
|
|||
import { SearchResponse } from 'elasticsearch';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
|
||||
import { kibanaRequestToMetadataListESQuery, getESQueryHostMetadataByID } from './query_builders';
|
||||
import { HostInfo, HostMetadata, HostResultList, HostStatus } from '../../../common/types';
|
||||
import { EndpointAppContext } from '../../types';
|
||||
import { getESQueryHostMetadataByID, kibanaRequestToMetadataListESQuery } from './query_builders';
|
||||
|
||||
interface HitSource {
|
||||
_source: HostMetadata;
|
||||
|
@ -50,7 +50,14 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp
|
|||
},
|
||||
async (context, req, res) => {
|
||||
try {
|
||||
const queryParams = await kibanaRequestToMetadataListESQuery(req, endpointAppContext);
|
||||
const index = await endpointAppContext.indexPatternRetriever.getMetadataIndexPattern(
|
||||
context
|
||||
);
|
||||
const queryParams = await kibanaRequestToMetadataListESQuery(
|
||||
req,
|
||||
endpointAppContext,
|
||||
index
|
||||
);
|
||||
const response = (await context.core.elasticsearch.dataClient.callAsCurrentUser(
|
||||
'search',
|
||||
queryParams
|
||||
|
@ -72,7 +79,11 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp
|
|||
},
|
||||
async (context, req, res) => {
|
||||
try {
|
||||
const doc = await getHostData(context, req.params.id);
|
||||
const index = await endpointAppContext.indexPatternRetriever.getMetadataIndexPattern(
|
||||
context
|
||||
);
|
||||
|
||||
const doc = await getHostData(context, req.params.id, index);
|
||||
if (doc) {
|
||||
return res.ok({ body: doc });
|
||||
}
|
||||
|
@ -86,9 +97,10 @@ export function registerEndpointRoutes(router: IRouter, endpointAppContext: Endp
|
|||
|
||||
export async function getHostData(
|
||||
context: RequestHandlerContext,
|
||||
id: string
|
||||
id: string,
|
||||
index: string
|
||||
): Promise<HostInfo | undefined> {
|
||||
const query = getESQueryHostMetadataByID(id);
|
||||
const query = getESQueryHostMetadataByID(id, index);
|
||||
const response = (await context.core.elasticsearch.dataClient.callAsCurrentUser(
|
||||
'search',
|
||||
query
|
||||
|
|
|
@ -11,24 +11,28 @@ import {
|
|||
RequestHandler,
|
||||
RequestHandlerContext,
|
||||
RouteConfig,
|
||||
SavedObjectsClientContract,
|
||||
} from 'kibana/server';
|
||||
import {
|
||||
elasticsearchServiceMock,
|
||||
httpServerMock,
|
||||
httpServiceMock,
|
||||
loggingServiceMock,
|
||||
savedObjectsClientMock,
|
||||
} from '../../../../../../src/core/server/mocks';
|
||||
import { HostInfo, HostMetadata, HostResultList, HostStatus } from '../../../common/types';
|
||||
import { SearchResponse } from 'elasticsearch';
|
||||
import { registerEndpointRoutes } from './index';
|
||||
import { EndpointConfigSchema } from '../../config';
|
||||
import * as data from '../../test_data/all_metadata_data.json';
|
||||
import { registerEndpointRoutes } from './index';
|
||||
import { createMockMetadataIndexPatternRetriever } from '../../mocks';
|
||||
|
||||
describe('test endpoint route', () => {
|
||||
let routerMock: jest.Mocked<IRouter>;
|
||||
let mockResponse: jest.Mocked<KibanaResponseFactory>;
|
||||
let mockClusterClient: jest.Mocked<IClusterClient>;
|
||||
let mockScopedClient: jest.Mocked<IScopedClusterClient>;
|
||||
let mockSavedObjectClient: jest.Mocked<SavedObjectsClientContract>;
|
||||
let routeHandler: RequestHandler<any, any, any>;
|
||||
let routeConfig: RouteConfig<any, any, any, any>;
|
||||
|
||||
|
@ -37,15 +41,38 @@ describe('test endpoint route', () => {
|
|||
IClusterClient
|
||||
>;
|
||||
mockScopedClient = elasticsearchServiceMock.createScopedClusterClient();
|
||||
mockSavedObjectClient = savedObjectsClientMock.create();
|
||||
mockClusterClient.asScoped.mockReturnValue(mockScopedClient);
|
||||
routerMock = httpServiceMock.createRouter();
|
||||
mockResponse = httpServerMock.createResponseFactory();
|
||||
registerEndpointRoutes(routerMock, {
|
||||
indexPatternRetriever: createMockMetadataIndexPatternRetriever(),
|
||||
logFactory: loggingServiceMock.create(),
|
||||
config: () => Promise.resolve(EndpointConfigSchema.validate({})),
|
||||
});
|
||||
});
|
||||
|
||||
function createRouteHandlerContext(
|
||||
dataClient: jest.Mocked<IScopedClusterClient>,
|
||||
savedObjectsClient: jest.Mocked<SavedObjectsClientContract>
|
||||
) {
|
||||
return ({
|
||||
core: {
|
||||
elasticsearch: {
|
||||
dataClient,
|
||||
},
|
||||
savedObjects: {
|
||||
client: savedObjectsClient,
|
||||
},
|
||||
},
|
||||
/**
|
||||
* Using unknown here because the object defined is not a full `RequestHandlerContext`. We don't
|
||||
* need all of the fields required to run the tests, but the `routeHandler` function requires a
|
||||
* `RequestHandlerContext`.
|
||||
*/
|
||||
} as unknown) as RequestHandlerContext;
|
||||
}
|
||||
|
||||
it('test find the latest of all endpoints', async () => {
|
||||
const mockRequest = httpServerMock.createKibanaRequest({});
|
||||
|
||||
|
@ -58,13 +85,7 @@ describe('test endpoint route', () => {
|
|||
)!;
|
||||
|
||||
await routeHandler(
|
||||
({
|
||||
core: {
|
||||
elasticsearch: {
|
||||
dataClient: mockScopedClient,
|
||||
},
|
||||
},
|
||||
} as unknown) as RequestHandlerContext,
|
||||
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient),
|
||||
mockRequest,
|
||||
mockResponse
|
||||
);
|
||||
|
@ -100,13 +121,7 @@ describe('test endpoint route', () => {
|
|||
)!;
|
||||
|
||||
await routeHandler(
|
||||
({
|
||||
core: {
|
||||
elasticsearch: {
|
||||
dataClient: mockScopedClient,
|
||||
},
|
||||
},
|
||||
} as unknown) as RequestHandlerContext,
|
||||
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient),
|
||||
mockRequest,
|
||||
mockResponse
|
||||
);
|
||||
|
@ -147,13 +162,7 @@ describe('test endpoint route', () => {
|
|||
)!;
|
||||
|
||||
await routeHandler(
|
||||
({
|
||||
core: {
|
||||
elasticsearch: {
|
||||
dataClient: mockScopedClient,
|
||||
},
|
||||
},
|
||||
} as unknown) as RequestHandlerContext,
|
||||
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient),
|
||||
mockRequest,
|
||||
mockResponse
|
||||
);
|
||||
|
@ -212,13 +221,7 @@ describe('test endpoint route', () => {
|
|||
)!;
|
||||
|
||||
await routeHandler(
|
||||
({
|
||||
core: {
|
||||
elasticsearch: {
|
||||
dataClient: mockScopedClient,
|
||||
},
|
||||
},
|
||||
} as unknown) as RequestHandlerContext,
|
||||
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient),
|
||||
mockRequest,
|
||||
mockResponse
|
||||
);
|
||||
|
@ -243,13 +246,7 @@ describe('test endpoint route', () => {
|
|||
)!;
|
||||
|
||||
await routeHandler(
|
||||
({
|
||||
core: {
|
||||
elasticsearch: {
|
||||
dataClient: mockScopedClient,
|
||||
},
|
||||
},
|
||||
} as unknown) as RequestHandlerContext,
|
||||
createRouteHandlerContext(mockScopedClient, mockSavedObjectClient),
|
||||
mockRequest,
|
||||
mockResponse
|
||||
);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import { httpServerMock, loggingServiceMock } from '../../../../../../src/core/server/mocks';
|
||||
import { EndpointConfigSchema } from '../../config';
|
||||
import { kibanaRequestToMetadataListESQuery, getESQueryHostMetadataByID } from './query_builders';
|
||||
import { EndpointAppConstants } from '../../../common/types';
|
||||
import { createMockMetadataIndexPatternRetriever, MetadataIndexPattern } from '../../mocks';
|
||||
|
||||
describe('query builder', () => {
|
||||
describe('MetadataListESQuery', () => {
|
||||
|
@ -14,17 +14,22 @@ describe('query builder', () => {
|
|||
const mockRequest = httpServerMock.createKibanaRequest({
|
||||
body: {},
|
||||
});
|
||||
const query = await kibanaRequestToMetadataListESQuery(mockRequest, {
|
||||
logFactory: loggingServiceMock.create(),
|
||||
config: () => Promise.resolve(EndpointConfigSchema.validate({})),
|
||||
});
|
||||
const query = await kibanaRequestToMetadataListESQuery(
|
||||
mockRequest,
|
||||
{
|
||||
indexPatternRetriever: createMockMetadataIndexPatternRetriever(),
|
||||
logFactory: loggingServiceMock.create(),
|
||||
config: () => Promise.resolve(EndpointConfigSchema.validate({})),
|
||||
},
|
||||
MetadataIndexPattern
|
||||
);
|
||||
expect(query).toEqual({
|
||||
body: {
|
||||
query: {
|
||||
match_all: {},
|
||||
},
|
||||
collapse: {
|
||||
field: 'host.id.keyword',
|
||||
field: 'host.id',
|
||||
inner_hits: {
|
||||
name: 'most_recent',
|
||||
size: 1,
|
||||
|
@ -34,7 +39,7 @@ describe('query builder', () => {
|
|||
aggs: {
|
||||
total: {
|
||||
cardinality: {
|
||||
field: 'host.id.keyword',
|
||||
field: 'host.id',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -48,7 +53,7 @@ describe('query builder', () => {
|
|||
},
|
||||
from: 0,
|
||||
size: 10,
|
||||
index: EndpointAppConstants.ENDPOINT_INDEX_NAME,
|
||||
index: MetadataIndexPattern,
|
||||
} as Record<string, any>);
|
||||
});
|
||||
});
|
||||
|
@ -60,10 +65,15 @@ describe('query builder', () => {
|
|||
filter: 'not host.ip:10.140.73.246',
|
||||
},
|
||||
});
|
||||
const query = await kibanaRequestToMetadataListESQuery(mockRequest, {
|
||||
logFactory: loggingServiceMock.create(),
|
||||
config: () => Promise.resolve(EndpointConfigSchema.validate({})),
|
||||
});
|
||||
const query = await kibanaRequestToMetadataListESQuery(
|
||||
mockRequest,
|
||||
{
|
||||
indexPatternRetriever: createMockMetadataIndexPatternRetriever(),
|
||||
logFactory: loggingServiceMock.create(),
|
||||
config: () => Promise.resolve(EndpointConfigSchema.validate({})),
|
||||
},
|
||||
MetadataIndexPattern
|
||||
);
|
||||
expect(query).toEqual({
|
||||
body: {
|
||||
query: {
|
||||
|
@ -83,7 +93,7 @@ describe('query builder', () => {
|
|||
},
|
||||
},
|
||||
collapse: {
|
||||
field: 'host.id.keyword',
|
||||
field: 'host.id',
|
||||
inner_hits: {
|
||||
name: 'most_recent',
|
||||
size: 1,
|
||||
|
@ -93,7 +103,7 @@ describe('query builder', () => {
|
|||
aggs: {
|
||||
total: {
|
||||
cardinality: {
|
||||
field: 'host.id.keyword',
|
||||
field: 'host.id',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -107,7 +117,7 @@ describe('query builder', () => {
|
|||
},
|
||||
from: 0,
|
||||
size: 10,
|
||||
index: EndpointAppConstants.ENDPOINT_INDEX_NAME,
|
||||
index: MetadataIndexPattern,
|
||||
} as Record<string, any>);
|
||||
});
|
||||
});
|
||||
|
@ -115,14 +125,15 @@ describe('query builder', () => {
|
|||
describe('MetadataGetQuery', () => {
|
||||
it('searches for the correct ID', () => {
|
||||
const mockID = 'AABBCCDD-0011-2233-AA44-DEADBEEF8899';
|
||||
const query = getESQueryHostMetadataByID(mockID);
|
||||
const query = getESQueryHostMetadataByID(mockID, MetadataIndexPattern);
|
||||
|
||||
expect(query).toEqual({
|
||||
body: {
|
||||
query: { match: { 'host.id.keyword': mockID } },
|
||||
query: { match: { 'host.id': mockID } },
|
||||
sort: [{ 'event.created': { order: 'desc' } }],
|
||||
size: 1,
|
||||
},
|
||||
index: EndpointAppConstants.ENDPOINT_INDEX_NAME,
|
||||
index: MetadataIndexPattern,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -6,18 +6,18 @@
|
|||
import { KibanaRequest } from 'kibana/server';
|
||||
import { esKuery } from '../../../../../../src/plugins/data/server';
|
||||
import { EndpointAppContext } from '../../types';
|
||||
import { EndpointAppConstants } from '../../../common/types';
|
||||
|
||||
export const kibanaRequestToMetadataListESQuery = async (
|
||||
request: KibanaRequest<any, any, any>,
|
||||
endpointAppContext: EndpointAppContext
|
||||
endpointAppContext: EndpointAppContext,
|
||||
index: string
|
||||
): Promise<Record<string, any>> => {
|
||||
const pagingProperties = await getPagingProperties(request, endpointAppContext);
|
||||
return {
|
||||
body: {
|
||||
query: buildQueryBody(request),
|
||||
collapse: {
|
||||
field: 'host.id.keyword',
|
||||
field: 'host.id',
|
||||
inner_hits: {
|
||||
name: 'most_recent',
|
||||
size: 1,
|
||||
|
@ -27,7 +27,7 @@ export const kibanaRequestToMetadataListESQuery = async (
|
|||
aggs: {
|
||||
total: {
|
||||
cardinality: {
|
||||
field: 'host.id.keyword',
|
||||
field: 'host.id',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -41,7 +41,7 @@ export const kibanaRequestToMetadataListESQuery = async (
|
|||
},
|
||||
from: pagingProperties.pageIndex * pagingProperties.pageSize,
|
||||
size: pagingProperties.pageSize,
|
||||
index: EndpointAppConstants.ENDPOINT_INDEX_NAME,
|
||||
index,
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -74,12 +74,12 @@ function buildQueryBody(request: KibanaRequest<any, any, any>): Record<string, a
|
|||
};
|
||||
}
|
||||
|
||||
export function getESQueryHostMetadataByID(hostID: string) {
|
||||
export function getESQueryHostMetadataByID(hostID: string, index: string) {
|
||||
return {
|
||||
body: {
|
||||
query: {
|
||||
match: {
|
||||
'host.id.keyword': hostID,
|
||||
'host.id': hostID,
|
||||
},
|
||||
},
|
||||
sort: [
|
||||
|
@ -91,6 +91,6 @@ export function getESQueryHostMetadataByID(hostID: string) {
|
|||
],
|
||||
size: 1,
|
||||
},
|
||||
index: EndpointAppConstants.ENDPOINT_INDEX_NAME,
|
||||
index,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import { handleLifecycle, validateLifecycle } from './resolver/lifecycle';
|
|||
|
||||
export function registerResolverRoutes(router: IRouter, endpointAppContext: EndpointAppContext) {
|
||||
const log = endpointAppContext.logFactory.get('resolver');
|
||||
const indexPatternService = endpointAppContext.indexPatternRetriever;
|
||||
|
||||
router.get(
|
||||
{
|
||||
|
@ -19,7 +20,7 @@ export function registerResolverRoutes(router: IRouter, endpointAppContext: Endp
|
|||
validate: validateRelatedEvents,
|
||||
options: { authRequired: true },
|
||||
},
|
||||
handleRelatedEvents(log)
|
||||
handleRelatedEvents(log, indexPatternService)
|
||||
);
|
||||
|
||||
router.get(
|
||||
|
@ -28,7 +29,7 @@ export function registerResolverRoutes(router: IRouter, endpointAppContext: Endp
|
|||
validate: validateChildren,
|
||||
options: { authRequired: true },
|
||||
},
|
||||
handleChildren(log)
|
||||
handleChildren(log, indexPatternService)
|
||||
);
|
||||
|
||||
router.get(
|
||||
|
@ -37,6 +38,6 @@ export function registerResolverRoutes(router: IRouter, endpointAppContext: Endp
|
|||
validate: validateLifecycle,
|
||||
options: { authRequired: true },
|
||||
},
|
||||
handleLifecycle(log)
|
||||
handleLifecycle(log, indexPatternService)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import { extractEntityID } from './utils/normalize';
|
|||
import { getPaginationParams } from './utils/pagination';
|
||||
import { LifecycleQuery } from './queries/lifecycle';
|
||||
import { ChildrenQuery } from './queries/children';
|
||||
import { IndexPatternRetriever } from '../../index_pattern';
|
||||
|
||||
interface ChildrenQueryParams {
|
||||
after?: string;
|
||||
|
@ -45,7 +46,8 @@ export const validateChildren = {
|
|||
};
|
||||
|
||||
export function handleChildren(
|
||||
log: Logger
|
||||
log: Logger,
|
||||
indexRetriever: IndexPatternRetriever
|
||||
): RequestHandler<ChildrenPathParams, ChildrenQueryParams> {
|
||||
return async (context, req, res) => {
|
||||
const {
|
||||
|
@ -54,10 +56,11 @@ export function handleChildren(
|
|||
} = req;
|
||||
try {
|
||||
const pagination = getPaginationParams(limit, after);
|
||||
const indexPattern = await indexRetriever.getEventIndexPattern(context);
|
||||
|
||||
const client = context.core.elasticsearch.dataClient;
|
||||
const childrenQuery = new ChildrenQuery(legacyEndpointID, pagination);
|
||||
const lifecycleQuery = new LifecycleQuery(legacyEndpointID);
|
||||
const childrenQuery = new ChildrenQuery(indexPattern, legacyEndpointID, pagination);
|
||||
const lifecycleQuery = new LifecycleQuery(indexPattern, legacyEndpointID);
|
||||
|
||||
// Retrieve the related child process events for a given process
|
||||
const { total, results: events, nextCursor } = await childrenQuery.search(client, id);
|
||||
|
|
|
@ -10,6 +10,7 @@ import { RequestHandler, Logger } from 'kibana/server';
|
|||
import { extractParentEntityID } from './utils/normalize';
|
||||
import { LifecycleQuery } from './queries/lifecycle';
|
||||
import { ResolverEvent } from '../../../common/types';
|
||||
import { IndexPatternRetriever } from '../../index_pattern';
|
||||
|
||||
interface LifecycleQueryParams {
|
||||
ancestors: number;
|
||||
|
@ -46,7 +47,8 @@ function getParentEntityID(results: ResolverEvent[]) {
|
|||
}
|
||||
|
||||
export function handleLifecycle(
|
||||
log: Logger
|
||||
log: Logger,
|
||||
indexRetriever: IndexPatternRetriever
|
||||
): RequestHandler<LifecyclePathParams, LifecycleQueryParams> {
|
||||
return async (context, req, res) => {
|
||||
const {
|
||||
|
@ -56,8 +58,8 @@ export function handleLifecycle(
|
|||
try {
|
||||
const ancestorLifecycles = [];
|
||||
const client = context.core.elasticsearch.dataClient;
|
||||
|
||||
const lifecycleQuery = new LifecycleQuery(legacyEndpointID);
|
||||
const indexPattern = await indexRetriever.getEventIndexPattern(context);
|
||||
const lifecycleQuery = new LifecycleQuery(indexPattern, legacyEndpointID);
|
||||
const { results: processLifecycle } = await lifecycleQuery.search(client, id);
|
||||
let nextParentID = getParentEntityID(processLifecycle);
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { JsonObject } from '../../../../../../../src/plugins/kibana_utils/public
|
|||
|
||||
export abstract class ResolverQuery {
|
||||
constructor(
|
||||
private readonly indexPattern: string,
|
||||
private readonly endpointID?: string,
|
||||
private readonly pagination?: PaginationParams
|
||||
) {}
|
||||
|
@ -26,7 +27,7 @@ export abstract class ResolverQuery {
|
|||
if (this.endpointID) {
|
||||
return this.legacyQuery(this.endpointID, ids, EndpointAppConstants.LEGACY_EVENT_INDEX_NAME);
|
||||
}
|
||||
return this.query(ids, EndpointAppConstants.EVENT_INDEX_NAME);
|
||||
return this.query(ids, this.indexPattern);
|
||||
}
|
||||
|
||||
async search(client: IScopedClusterClient, ...ids: string[]) {
|
||||
|
|
|
@ -6,11 +6,17 @@
|
|||
import { ChildrenQuery } from './children';
|
||||
import { EndpointAppConstants } from '../../../../common/types';
|
||||
|
||||
export const fakeEventIndexPattern = 'events-endpoint-*';
|
||||
|
||||
describe('children events query', () => {
|
||||
it('generates the correct legacy queries', () => {
|
||||
const timestamp = new Date().getTime();
|
||||
expect(
|
||||
new ChildrenQuery('awesome-id', { size: 1, timestamp, eventID: 'foo' }).build('5')
|
||||
new ChildrenQuery(EndpointAppConstants.LEGACY_EVENT_INDEX_NAME, 'awesome-id', {
|
||||
size: 1,
|
||||
timestamp,
|
||||
eventID: 'foo',
|
||||
}).build('5')
|
||||
).toStrictEqual({
|
||||
body: {
|
||||
query: {
|
||||
|
@ -50,7 +56,11 @@ describe('children events query', () => {
|
|||
const timestamp = new Date().getTime();
|
||||
|
||||
expect(
|
||||
new ChildrenQuery(undefined, { size: 1, timestamp, eventID: 'bar' }).build('baz')
|
||||
new ChildrenQuery(fakeEventIndexPattern, undefined, {
|
||||
size: 1,
|
||||
timestamp,
|
||||
eventID: 'bar',
|
||||
}).build('baz')
|
||||
).toStrictEqual({
|
||||
body: {
|
||||
query: {
|
||||
|
@ -88,7 +98,7 @@ describe('children events query', () => {
|
|||
size: 1,
|
||||
sort: [{ '@timestamp': 'asc' }, { 'event.id': 'asc' }],
|
||||
},
|
||||
index: EndpointAppConstants.EVENT_INDEX_NAME,
|
||||
index: fakeEventIndexPattern,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,10 +5,13 @@
|
|||
*/
|
||||
import { EndpointAppConstants } from '../../../../common/types';
|
||||
import { LifecycleQuery } from './lifecycle';
|
||||
import { fakeEventIndexPattern } from './children.test';
|
||||
|
||||
describe('lifecycle query', () => {
|
||||
it('generates the correct legacy queries', () => {
|
||||
expect(new LifecycleQuery('awesome-id').build('5')).toStrictEqual({
|
||||
expect(
|
||||
new LifecycleQuery(EndpointAppConstants.LEGACY_EVENT_INDEX_NAME, 'awesome-id').build('5')
|
||||
).toStrictEqual({
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
|
@ -32,7 +35,7 @@ describe('lifecycle query', () => {
|
|||
});
|
||||
|
||||
it('generates the correct non-legacy queries', () => {
|
||||
expect(new LifecycleQuery().build('baz')).toStrictEqual({
|
||||
expect(new LifecycleQuery(fakeEventIndexPattern).build('baz')).toStrictEqual({
|
||||
body: {
|
||||
query: {
|
||||
bool: {
|
||||
|
@ -57,7 +60,7 @@ describe('lifecycle query', () => {
|
|||
},
|
||||
sort: [{ '@timestamp': 'asc' }],
|
||||
},
|
||||
index: EndpointAppConstants.EVENT_INDEX_NAME,
|
||||
index: fakeEventIndexPattern,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5,12 +5,17 @@
|
|||
*/
|
||||
import { RelatedEventsQuery } from './related_events';
|
||||
import { EndpointAppConstants } from '../../../../common/types';
|
||||
import { fakeEventIndexPattern } from './children.test';
|
||||
|
||||
describe('related events query', () => {
|
||||
it('generates the correct legacy queries', () => {
|
||||
const timestamp = new Date().getTime();
|
||||
expect(
|
||||
new RelatedEventsQuery('awesome-id', { size: 1, timestamp, eventID: 'foo' }).build('5')
|
||||
new RelatedEventsQuery(EndpointAppConstants.LEGACY_EVENT_INDEX_NAME, 'awesome-id', {
|
||||
size: 1,
|
||||
timestamp,
|
||||
eventID: 'foo',
|
||||
}).build('5')
|
||||
).toStrictEqual({
|
||||
body: {
|
||||
query: {
|
||||
|
@ -51,7 +56,11 @@ describe('related events query', () => {
|
|||
const timestamp = new Date().getTime();
|
||||
|
||||
expect(
|
||||
new RelatedEventsQuery(undefined, { size: 1, timestamp, eventID: 'bar' }).build('baz')
|
||||
new RelatedEventsQuery(fakeEventIndexPattern, undefined, {
|
||||
size: 1,
|
||||
timestamp,
|
||||
eventID: 'bar',
|
||||
}).build('baz')
|
||||
).toStrictEqual({
|
||||
body: {
|
||||
query: {
|
||||
|
@ -90,7 +99,7 @@ describe('related events query', () => {
|
|||
size: 1,
|
||||
sort: [{ '@timestamp': 'asc' }, { 'event.id': 'asc' }],
|
||||
},
|
||||
index: EndpointAppConstants.EVENT_INDEX_NAME,
|
||||
index: fakeEventIndexPattern,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -8,6 +8,7 @@ import { schema } from '@kbn/config-schema';
|
|||
import { RequestHandler, Logger } from 'kibana/server';
|
||||
import { getPaginationParams } from './utils/pagination';
|
||||
import { RelatedEventsQuery } from './queries/related_events';
|
||||
import { IndexPatternRetriever } from '../../index_pattern';
|
||||
|
||||
interface RelatedEventsQueryParams {
|
||||
after?: string;
|
||||
|
@ -42,7 +43,8 @@ export const validateRelatedEvents = {
|
|||
};
|
||||
|
||||
export function handleRelatedEvents(
|
||||
log: Logger
|
||||
log: Logger,
|
||||
indexRetriever: IndexPatternRetriever
|
||||
): RequestHandler<RelatedEventsPathParams, RelatedEventsQueryParams> {
|
||||
return async (context, req, res) => {
|
||||
const {
|
||||
|
@ -53,8 +55,9 @@ export function handleRelatedEvents(
|
|||
const pagination = getPaginationParams(limit, after);
|
||||
|
||||
const client = context.core.elasticsearch.dataClient;
|
||||
const indexPattern = await indexRetriever.getEventIndexPattern(context);
|
||||
// Retrieve the related non-process events for a given process
|
||||
const relatedEventsQuery = new RelatedEventsQuery(legacyEndpointID, pagination);
|
||||
const relatedEventsQuery = new RelatedEventsQuery(indexPattern, legacyEndpointID, pagination);
|
||||
const relatedEvents = await relatedEventsQuery.search(client, id);
|
||||
|
||||
const { total, results: events, nextCursor } = relatedEvents;
|
||||
|
|
|
@ -1,115 +1,109 @@
|
|||
{
|
||||
"took" : 343,
|
||||
"timed_out" : false,
|
||||
"_shards" : {
|
||||
"total" : 1,
|
||||
"successful" : 1,
|
||||
"skipped" : 0,
|
||||
"failed" : 0
|
||||
"took": 343,
|
||||
"timed_out": false,
|
||||
"_shards": {
|
||||
"total": 1,
|
||||
"successful": 1,
|
||||
"skipped": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"hits" : {
|
||||
"total" : {
|
||||
"value" : 4,
|
||||
"relation" : "eq"
|
||||
"hits": {
|
||||
"total": {
|
||||
"value": 4,
|
||||
"relation": "eq"
|
||||
},
|
||||
"max_score" : null,
|
||||
"hits" : [
|
||||
"max_score": null,
|
||||
"hits": [
|
||||
{
|
||||
"_index" : "endpoint-agent",
|
||||
"_id" : "WqVo1G8BYQH1gtPUgYkC",
|
||||
"_score" : null,
|
||||
"_source" : {
|
||||
"@timestamp" : 1579816615336,
|
||||
"event" : {
|
||||
"created" : "2020-01-23T21:56:55.336Z"
|
||||
"_index": "metadata-endpoint-default-1",
|
||||
"_id": "WqVo1G8BYQH1gtPUgYkC",
|
||||
"_score": null,
|
||||
"_source": {
|
||||
"@timestamp": 1579816615336,
|
||||
"event": {
|
||||
"created": "2020-01-23T21:56:55.336Z"
|
||||
},
|
||||
"elastic": {
|
||||
"agent": {
|
||||
"id": "56a75650-3c8a-4e4f-ac17-6dd729c650e2"
|
||||
}
|
||||
},
|
||||
"endpoint" : {
|
||||
"policy" : {
|
||||
"id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
|
||||
"endpoint": {
|
||||
"policy": {
|
||||
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
|
||||
}
|
||||
},
|
||||
"agent" : {
|
||||
"version" : "6.8.3",
|
||||
"id" : "56a75650-3c8a-4e4f-ac17-6dd729c650e2",
|
||||
"agent": {
|
||||
"version": "6.8.3",
|
||||
"id": "56a75650-3c8a-4e4f-ac17-6dd729c650e2",
|
||||
"name": "Elastic Endpoint"
|
||||
},
|
||||
"host" : {
|
||||
"id" : "7141a48b-e19f-4ae3-89a0-6e7179a84265",
|
||||
"hostname" : "larimer-0.example.com",
|
||||
"ip" : "10.21.48.136",
|
||||
"mac" : "77-be-30-f0-e8-d6",
|
||||
"architecture" : "x86_64",
|
||||
"os" : {
|
||||
"name" : "windows 6.2",
|
||||
"full" : "Windows Server 2012",
|
||||
"version" : "6.2",
|
||||
"variant" : "Windows Server"
|
||||
"host": {
|
||||
"id": "7141a48b-e19f-4ae3-89a0-6e7179a84265",
|
||||
"hostname": "larimer-0.example.com",
|
||||
"ip": "10.21.48.136",
|
||||
"mac": "77-be-30-f0-e8-d6",
|
||||
"architecture": "x86_64",
|
||||
"os": {
|
||||
"name": "windows 6.2",
|
||||
"full": "Windows Server 2012",
|
||||
"version": "6.2",
|
||||
"variant": "Windows Server"
|
||||
}
|
||||
}
|
||||
},
|
||||
"fields" : {
|
||||
"host.id.keyword" : [
|
||||
"7141a48b-e19f-4ae3-89a0-6e7179a84265"
|
||||
]
|
||||
"fields": {
|
||||
"host.id.keyword": ["7141a48b-e19f-4ae3-89a0-6e7179a84265"]
|
||||
},
|
||||
"sort" : [
|
||||
1579816615336
|
||||
],
|
||||
"inner_hits" : {
|
||||
"most_recent" : {
|
||||
"hits" : {
|
||||
"total" : {
|
||||
"value" : 2,
|
||||
"relation" : "eq"
|
||||
"sort": [1579816615336],
|
||||
"inner_hits": {
|
||||
"most_recent": {
|
||||
"hits": {
|
||||
"total": {
|
||||
"value": 2,
|
||||
"relation": "eq"
|
||||
},
|
||||
"max_score" : null,
|
||||
"hits" : [
|
||||
"max_score": null,
|
||||
"hits": [
|
||||
{
|
||||
"_index" : "endpoint-agent",
|
||||
"_id" : "WqVo1G8BYQH1gtPUgYkC",
|
||||
"_score" : null,
|
||||
"_source" : {
|
||||
"@timestamp" : 1579816615336,
|
||||
"event" : {
|
||||
"created" : "2020-01-23T21:56:55.336Z"
|
||||
"_index": "metadata-endpoint-default-1",
|
||||
"_id": "WqVo1G8BYQH1gtPUgYkC",
|
||||
"_score": null,
|
||||
"_source": {
|
||||
"@timestamp": 1579816615336,
|
||||
"event": {
|
||||
"created": "2020-01-23T21:56:55.336Z"
|
||||
},
|
||||
"elastic": {
|
||||
"agent": {
|
||||
"id": "56a75650-3c8a-4e4f-ac17-6dd729c650e2"
|
||||
}
|
||||
},
|
||||
"endpoint" : {
|
||||
"policy" : {
|
||||
"id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
|
||||
"endpoint": {
|
||||
"policy": {
|
||||
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
|
||||
}
|
||||
},
|
||||
"agent" : {
|
||||
"version" : "6.8.3",
|
||||
"id" : "56a75650-3c8a-4e4f-ac17-6dd729c650e2",
|
||||
"agent": {
|
||||
"version": "6.8.3",
|
||||
"id": "56a75650-3c8a-4e4f-ac17-6dd729c650e2",
|
||||
"name": "Elastic Endpoint"
|
||||
},
|
||||
"host" : {
|
||||
"id" : "7141a48b-e19f-4ae3-89a0-6e7179a84265",
|
||||
"hostname" : "larimer-0.example.com",
|
||||
"ip" : "10.21.48.136",
|
||||
"mac" : "77-be-30-f0-e8-d6",
|
||||
"architecture" : "x86_64",
|
||||
"os" : {
|
||||
"name" : "windows 6.2",
|
||||
"full" : "Windows Server 2012",
|
||||
"version" : "6.2",
|
||||
"variant" : "Windows Server"
|
||||
"host": {
|
||||
"id": "7141a48b-e19f-4ae3-89a0-6e7179a84265",
|
||||
"hostname": "larimer-0.example.com",
|
||||
"ip": "10.21.48.136",
|
||||
"mac": "77-be-30-f0-e8-d6",
|
||||
"architecture": "x86_64",
|
||||
"os": {
|
||||
"name": "windows 6.2",
|
||||
"full": "Windows Server 2012",
|
||||
"version": "6.2",
|
||||
"variant": "Windows Server"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sort" : [
|
||||
1579816615336
|
||||
]
|
||||
"sort": [1579816615336]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -117,101 +111,95 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"_index" : "endpoint-agent",
|
||||
"_id" : "W6Vo1G8BYQH1gtPUgYkC",
|
||||
"_score" : null,
|
||||
"_source" : {
|
||||
"@timestamp" : 1579816615336,
|
||||
"event" : {
|
||||
"created" : "2020-01-23T21:56:55.336Z"
|
||||
"_index": "metadata-endpoint-default-1",
|
||||
"_id": "W6Vo1G8BYQH1gtPUgYkC",
|
||||
"_score": null,
|
||||
"_source": {
|
||||
"@timestamp": 1579816615336,
|
||||
"event": {
|
||||
"created": "2020-01-23T21:56:55.336Z"
|
||||
},
|
||||
"elastic": {
|
||||
"agent": {
|
||||
"id": "c2d84d8f-d355-40de-8b54-5d318d4d1312"
|
||||
}
|
||||
},
|
||||
"endpoint" : {
|
||||
"policy" : {
|
||||
"id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
|
||||
"endpoint": {
|
||||
"policy": {
|
||||
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
|
||||
}
|
||||
},
|
||||
"agent" : {
|
||||
"version" : "6.4.3",
|
||||
"id" : "c2d84d8f-d355-40de-8b54-5d318d4d1312",
|
||||
"agent": {
|
||||
"version": "6.4.3",
|
||||
"id": "c2d84d8f-d355-40de-8b54-5d318d4d1312",
|
||||
"name": "Elastic Endpoint"
|
||||
},
|
||||
"host" : {
|
||||
"id" : "f35ec6c1-6562-45b1-818f-2f14c0854adf",
|
||||
"hostname" : "hildebrandt-6.example.com",
|
||||
"ip" : "10.53.92.84",
|
||||
"mac" : "af-f1-8f-51-25-2a",
|
||||
"architecture" : "x86_64",
|
||||
"os" : {
|
||||
"name" : "windows 10.0",
|
||||
"full" : "Windows 10",
|
||||
"version" : "10.0",
|
||||
"variant" : "Windows Pro"
|
||||
"host": {
|
||||
"id": "f35ec6c1-6562-45b1-818f-2f14c0854adf",
|
||||
"hostname": "hildebrandt-6.example.com",
|
||||
"ip": "10.53.92.84",
|
||||
"mac": "af-f1-8f-51-25-2a",
|
||||
"architecture": "x86_64",
|
||||
"os": {
|
||||
"name": "windows 10.0",
|
||||
"full": "Windows 10",
|
||||
"version": "10.0",
|
||||
"variant": "Windows Pro"
|
||||
}
|
||||
}
|
||||
},
|
||||
"fields" : {
|
||||
"host.id.keyword" : [
|
||||
"f35ec6c1-6562-45b1-818f-2f14c0854adf"
|
||||
]
|
||||
"fields": {
|
||||
"host.id.keyword": ["f35ec6c1-6562-45b1-818f-2f14c0854adf"]
|
||||
},
|
||||
"sort" : [
|
||||
1579816615336
|
||||
],
|
||||
"inner_hits" : {
|
||||
"most_recent" : {
|
||||
"hits" : {
|
||||
"total" : {
|
||||
"value" : 2,
|
||||
"relation" : "eq"
|
||||
"sort": [1579816615336],
|
||||
"inner_hits": {
|
||||
"most_recent": {
|
||||
"hits": {
|
||||
"total": {
|
||||
"value": 2,
|
||||
"relation": "eq"
|
||||
},
|
||||
"max_score" : null,
|
||||
"hits" : [
|
||||
"max_score": null,
|
||||
"hits": [
|
||||
{
|
||||
"_index" : "endpoint-agent",
|
||||
"_id" : "W6Vo1G8BYQH1gtPUgYkC",
|
||||
"_score" : null,
|
||||
"_source" : {
|
||||
"@timestamp" : 1579816615336,
|
||||
"event" : {
|
||||
"created" : "2020-01-23T21:56:55.336Z"
|
||||
"_index": "metadata-endpoint-default-1",
|
||||
"_id": "W6Vo1G8BYQH1gtPUgYkC",
|
||||
"_score": null,
|
||||
"_source": {
|
||||
"@timestamp": 1579816615336,
|
||||
"event": {
|
||||
"created": "2020-01-23T21:56:55.336Z"
|
||||
},
|
||||
"elastic": {
|
||||
"agent": {
|
||||
"id": "c2d84d8f-d355-40de-8b54-5d318d4d1312"
|
||||
}
|
||||
},
|
||||
"endpoint" : {
|
||||
"policy" : {
|
||||
"id" : "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
|
||||
"endpoint": {
|
||||
"policy": {
|
||||
"id": "C2A9093E-E289-4C0A-AA44-8C32A414FA7A"
|
||||
}
|
||||
},
|
||||
"agent" : {
|
||||
"version" : "6.4.3",
|
||||
"id" : "c2d84d8f-d355-40de-8b54-5d318d4d1312",
|
||||
"agent": {
|
||||
"version": "6.4.3",
|
||||
"id": "c2d84d8f-d355-40de-8b54-5d318d4d1312",
|
||||
"name": "Elastic Endpoint"
|
||||
},
|
||||
"host" : {
|
||||
"id" : "f35ec6c1-6562-45b1-818f-2f14c0854adf",
|
||||
"hostname" : "hildebrandt-6.example.com",
|
||||
"ip" : "10.53.92.84",
|
||||
"mac" : "af-f1-8f-51-25-2a",
|
||||
"architecture" : "x86_64",
|
||||
"os" : {
|
||||
"name" : "windows 10.0",
|
||||
"full" : "Windows 10",
|
||||
"version" : "10.0",
|
||||
"variant" : "Windows Pro"
|
||||
"host": {
|
||||
"id": "f35ec6c1-6562-45b1-818f-2f14c0854adf",
|
||||
"hostname": "hildebrandt-6.example.com",
|
||||
"ip": "10.53.92.84",
|
||||
"mac": "af-f1-8f-51-25-2a",
|
||||
"architecture": "x86_64",
|
||||
"os": {
|
||||
"name": "windows 10.0",
|
||||
"full": "Windows 10",
|
||||
"version": "10.0",
|
||||
"variant": "Windows Pro"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sort" : [
|
||||
1579816615336
|
||||
]
|
||||
"sort": [1579816615336]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -220,9 +208,9 @@
|
|||
}
|
||||
]
|
||||
},
|
||||
"aggregations" : {
|
||||
"total" : {
|
||||
"value" : 2
|
||||
"aggregations": {
|
||||
"total": {
|
||||
"value": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
*/
|
||||
import { LoggerFactory } from 'kibana/server';
|
||||
import { EndpointConfigType } from './config';
|
||||
import { IndexPatternRetriever } from './index_pattern';
|
||||
|
||||
/**
|
||||
* The context for Endpoint apps.
|
||||
*/
|
||||
export interface EndpointAppContext {
|
||||
indexPatternRetriever: IndexPatternRetriever;
|
||||
logFactory: LoggerFactory;
|
||||
config(): Promise<EndpointConfigType>;
|
||||
}
|
||||
|
|
|
@ -218,6 +218,7 @@ export type PackageInfo = Installable<
|
|||
|
||||
export interface Installation extends SavedObjectAttributes {
|
||||
installed: AssetReference[];
|
||||
es_index_patterns: Record<string, string>;
|
||||
name: string;
|
||||
version: string;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@ import { schema, TypeOf } from '@kbn/config-schema';
|
|||
import { PluginInitializerContext } from 'src/core/server';
|
||||
import { IngestManagerPlugin } from './plugin';
|
||||
|
||||
export { ESIndexPatternService } from './services';
|
||||
export { IngestManagerSetupContract } from './plugin';
|
||||
|
||||
export const config = {
|
||||
exposeToBrowser: {
|
||||
epm: true,
|
||||
|
|
|
@ -11,7 +11,9 @@ import {
|
|||
Plugin,
|
||||
PluginInitializerContext,
|
||||
SavedObjectsServiceStart,
|
||||
} from 'src/core/server';
|
||||
RecursiveReadonly,
|
||||
} from 'kibana/server';
|
||||
import { deepFreeze } from '../../../../src/core/utils';
|
||||
import { LicensingPluginSetup } from '../../licensing/server';
|
||||
import { EncryptedSavedObjectsPluginStart } from '../../encrypted_saved_objects/server';
|
||||
import { SecurityPluginSetup } from '../../security/server';
|
||||
|
@ -38,7 +40,18 @@ import {
|
|||
} from './routes';
|
||||
|
||||
import { IngestManagerConfigType } from '../common';
|
||||
import { appContextService } from './services';
|
||||
import {
|
||||
appContextService,
|
||||
ESIndexPatternService,
|
||||
ESIndexPatternSavedObjectService,
|
||||
} from './services';
|
||||
|
||||
/**
|
||||
* Describes public IngestManager plugin contract returned at the `setup` stage.
|
||||
*/
|
||||
export interface IngestManagerSetupContract {
|
||||
esIndexPatternService: ESIndexPatternService;
|
||||
}
|
||||
|
||||
export interface IngestManagerSetupDeps {
|
||||
licensing: LicensingPluginSetup;
|
||||
|
@ -63,7 +76,7 @@ const allSavedObjectTypes = [
|
|||
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
|
||||
];
|
||||
|
||||
export class IngestManagerPlugin implements Plugin {
|
||||
export class IngestManagerPlugin implements Plugin<IngestManagerSetupContract> {
|
||||
private config$: Observable<IngestManagerConfigType>;
|
||||
private security: SecurityPluginSetup | undefined;
|
||||
|
||||
|
@ -71,7 +84,10 @@ export class IngestManagerPlugin implements Plugin {
|
|||
this.config$ = this.initializerContext.config.create<IngestManagerConfigType>();
|
||||
}
|
||||
|
||||
public async setup(core: CoreSetup, deps: IngestManagerSetupDeps) {
|
||||
public async setup(
|
||||
core: CoreSetup,
|
||||
deps: IngestManagerSetupDeps
|
||||
): Promise<RecursiveReadonly<IngestManagerSetupContract>> {
|
||||
if (deps.security) {
|
||||
this.security = deps.security;
|
||||
}
|
||||
|
@ -130,6 +146,9 @@ export class IngestManagerPlugin implements Plugin {
|
|||
basePath: core.http.basePath,
|
||||
});
|
||||
}
|
||||
return deepFreeze({
|
||||
esIndexPatternService: new ESIndexPatternSavedObjectService(),
|
||||
});
|
||||
}
|
||||
|
||||
public async start(
|
||||
|
|
|
@ -150,6 +150,10 @@ export const savedObjectMappings = {
|
|||
name: { type: 'keyword' },
|
||||
version: { type: 'keyword' },
|
||||
internal: { type: 'boolean' },
|
||||
es_index_patterns: {
|
||||
dynamic: false,
|
||||
type: 'object',
|
||||
},
|
||||
installed: {
|
||||
type: 'nested',
|
||||
properties: {
|
||||
|
|
|
@ -136,6 +136,22 @@ export function generateTemplateName(dataset: Dataset): string {
|
|||
return getDatasetAssetBaseName(dataset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of the dataset path fields to elasticsearch index pattern.
|
||||
* @param datasets an array of Dataset objects
|
||||
*/
|
||||
export function generateESIndexPatterns(datasets: Dataset[] | undefined): Record<string, string> {
|
||||
if (!datasets) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const patterns: Record<string, string> = {};
|
||||
for (const dataset of datasets) {
|
||||
patterns[dataset.path] = generateTemplateName(dataset) + '-*';
|
||||
}
|
||||
return patterns;
|
||||
}
|
||||
|
||||
function getBaseTemplate(type: string, templateName: string, mappings: Mappings): IndexTemplate {
|
||||
return {
|
||||
// We need to decide which order we use for the templates
|
||||
|
|
|
@ -18,6 +18,7 @@ import * as Registry from '../registry';
|
|||
import { getObject } from './get_objects';
|
||||
import { getInstallation } from './index';
|
||||
import { installTemplates } from '../elasticsearch/template/install';
|
||||
import { generateESIndexPatterns } from '../elasticsearch/template/template';
|
||||
import { installPipelines } from '../elasticsearch/ingest_pipeline/install';
|
||||
import { installILMPolicy } from '../elasticsearch/ilm/install';
|
||||
|
||||
|
@ -117,17 +118,18 @@ export async function installPackage(options: {
|
|||
installTemplatePromises,
|
||||
]);
|
||||
|
||||
const toSave = res.flat();
|
||||
const toSaveAssetRefs: AssetReference[] = res.flat();
|
||||
const toSaveESIndexPatterns = generateESIndexPatterns(registryPackageInfo.datasets);
|
||||
// Save those references in the package manager's state saved object
|
||||
await saveInstallationReferences({
|
||||
return await saveInstallationReferences({
|
||||
savedObjectsClient,
|
||||
pkgkey,
|
||||
pkgName,
|
||||
pkgVersion,
|
||||
internal,
|
||||
toSave,
|
||||
toSaveAssetRefs,
|
||||
toSaveESIndexPatterns,
|
||||
});
|
||||
return toSave;
|
||||
}
|
||||
|
||||
// TODO: make it an exhaustive list
|
||||
|
@ -156,25 +158,44 @@ export async function saveInstallationReferences(options: {
|
|||
pkgName: string;
|
||||
pkgVersion: string;
|
||||
internal: boolean;
|
||||
toSave: AssetReference[];
|
||||
toSaveAssetRefs: AssetReference[];
|
||||
toSaveESIndexPatterns: Record<string, string>;
|
||||
}) {
|
||||
const { savedObjectsClient, pkgName, pkgVersion, internal, toSave } = options;
|
||||
const {
|
||||
savedObjectsClient,
|
||||
pkgName,
|
||||
pkgVersion,
|
||||
internal,
|
||||
toSaveAssetRefs,
|
||||
toSaveESIndexPatterns,
|
||||
} = options;
|
||||
const installation = await getInstallation({ savedObjectsClient, pkgName });
|
||||
const savedRefs = installation?.installed || [];
|
||||
const savedAssetRefs = installation?.installed || [];
|
||||
const toInstallESIndexPatterns = Object.assign(
|
||||
installation?.es_index_patterns || {},
|
||||
toSaveESIndexPatterns
|
||||
);
|
||||
|
||||
const mergeRefsReducer = (current: AssetReference[], pending: AssetReference) => {
|
||||
const hasRef = current.find(c => c.id === pending.id && c.type === pending.type);
|
||||
if (!hasRef) current.push(pending);
|
||||
return current;
|
||||
};
|
||||
|
||||
const toInstall = toSave.reduce(mergeRefsReducer, savedRefs);
|
||||
const toInstallAssetsRefs = toSaveAssetRefs.reduce(mergeRefsReducer, savedAssetRefs);
|
||||
await savedObjectsClient.create<Installation>(
|
||||
PACKAGES_SAVED_OBJECT_TYPE,
|
||||
{ installed: toInstall, name: pkgName, version: pkgVersion, internal },
|
||||
{
|
||||
installed: toInstallAssetsRefs,
|
||||
es_index_patterns: toInstallESIndexPatterns,
|
||||
name: pkgName,
|
||||
version: pkgVersion,
|
||||
internal,
|
||||
},
|
||||
{ id: pkgName, overwrite: true }
|
||||
);
|
||||
|
||||
return toInstall;
|
||||
return toInstallAssetsRefs;
|
||||
}
|
||||
|
||||
async function installKibanaSavedObjects({
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { SavedObjectsClientContract } from 'kibana/server';
|
||||
import { getInstallation } from './epm/packages/get';
|
||||
|
||||
export interface ESIndexPatternService {
|
||||
getESIndexPattern(
|
||||
savedObjectsClient: SavedObjectsClientContract,
|
||||
pkgName: string,
|
||||
datasetPath: string
|
||||
): Promise<string | undefined>;
|
||||
}
|
||||
|
||||
export class ESIndexPatternSavedObjectService implements ESIndexPatternService {
|
||||
public async getESIndexPattern(
|
||||
savedObjectsClient: SavedObjectsClientContract,
|
||||
pkgName: string,
|
||||
datasetPath: string
|
||||
): Promise<string | undefined> {
|
||||
const installation = await getInstallation({ savedObjectsClient, pkgName });
|
||||
return installation?.es_index_patterns[datasetPath];
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
export { appContextService } from './app_context';
|
||||
export { ESIndexPatternService, ESIndexPatternSavedObjectService } from './es_index_pattern';
|
||||
|
||||
// Saved object services
|
||||
export { datasourceService } from './datasource';
|
||||
|
|
|
@ -47,6 +47,7 @@ const onlyNotInCoverageTests = [
|
|||
require.resolve('../test/licensing_plugin/config.ts'),
|
||||
require.resolve('../test/licensing_plugin/config.public.ts'),
|
||||
require.resolve('../test/licensing_plugin/config.legacy.ts'),
|
||||
require.resolve('../test/endpoint_api_integration_no_ingest/config.ts'),
|
||||
];
|
||||
|
||||
require('@kbn/plugin-helpers').babelRegister();
|
||||
|
|
|
@ -6,9 +6,17 @@
|
|||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function endpointAPIIntegrationTests({ loadTestFile }: FtrProviderContext) {
|
||||
export default function endpointAPIIntegrationTests({
|
||||
loadTestFile,
|
||||
getService,
|
||||
}: FtrProviderContext) {
|
||||
describe('Endpoint plugin', function() {
|
||||
const ingestManager = getService('ingestManager');
|
||||
this.tags(['endpoint']);
|
||||
before(async () => {
|
||||
await ingestManager.setup();
|
||||
});
|
||||
loadTestFile(require.resolve('./index_pattern'));
|
||||
loadTestFile(require.resolve('./resolver'));
|
||||
loadTestFile(require.resolve('./metadata'));
|
||||
loadTestFile(require.resolve('./alerts'));
|
||||
|
|
27
x-pack/test/api_integration/apis/endpoint/index_pattern.ts
Normal file
27
x-pack/test/api_integration/apis/endpoint/index_pattern.ts
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import expect from '@kbn/expect/expect.js';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('Endpoint index pattern API', () => {
|
||||
it('should retrieve the index pattern for events', async () => {
|
||||
const { body } = await supertest.get('/api/endpoint/index_pattern/events').expect(200);
|
||||
expect(body.indexPattern).to.eql('events-endpoint-*');
|
||||
});
|
||||
|
||||
it('should retrieve the index pattern for metadata', async () => {
|
||||
const { body } = await supertest.get('/api/endpoint/index_pattern/metadata').expect(200);
|
||||
expect(body.indexPattern).to.eql('metrics-endpoint-*');
|
||||
});
|
||||
|
||||
it('should not retrieve the index pattern for an invalid key', async () => {
|
||||
await supertest.get('/api/endpoint/index_pattern/blah').expect(404);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -159,7 +159,7 @@ export default function({ getService }: FtrProviderContext) {
|
|||
.post('/api/endpoint/metadata')
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send({
|
||||
filter: `host.os.variant.keyword:${variantValue}`,
|
||||
filter: `host.os.variant:${variantValue}`,
|
||||
})
|
||||
.expect(200);
|
||||
expect(body.total).to.eql(2);
|
||||
|
|
|
@ -17,8 +17,8 @@ export default function resolverAPIIntegrationTests({ getService }: FtrProviderC
|
|||
const esArchiver = getService('esArchiver');
|
||||
|
||||
describe('Resolver', () => {
|
||||
before(() => esArchiver.load('endpoint/resolver/api_feature'));
|
||||
after(() => esArchiver.unload('endpoint/resolver/api_feature'));
|
||||
before(async () => await esArchiver.load('endpoint/resolver/api_feature'));
|
||||
after(async () => await esArchiver.unload('endpoint/resolver/api_feature'));
|
||||
|
||||
describe('related events endpoint', () => {
|
||||
const endpointID = '5a0c957f-b8e7-4538-965e-57e8bb86ad3a';
|
||||
|
|
|
@ -22,6 +22,7 @@ import {
|
|||
import { SiemGraphQLClientProvider, SiemGraphQLClientFactoryProvider } from './siem_graphql_client';
|
||||
import { InfraOpsSourceConfigurationProvider } from './infraops_source_configuration';
|
||||
import { MachineLearningProvider } from './ml';
|
||||
import { IngestManagerProvider } from './ingest_manager';
|
||||
|
||||
export const services = {
|
||||
...commonServices,
|
||||
|
@ -39,4 +40,5 @@ export const services = {
|
|||
supertestWithoutAuth: SupertestWithoutAuthProvider,
|
||||
usageAPI: UsageAPIProvider,
|
||||
ml: MachineLearningProvider,
|
||||
ingestManager: IngestManagerProvider,
|
||||
};
|
||||
|
|
28
x-pack/test/api_integration/services/ingest_manager.ts
Normal file
28
x-pack/test/api_integration/services/ingest_manager.ts
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
import { setupRouteService, fleetSetupRouteService } from '../../../plugins/ingest_manager/common';
|
||||
|
||||
export function IngestManagerProvider({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
return {
|
||||
async setup() {
|
||||
const headers = { accept: 'application/json', 'kbn-xsrf': 'some-xsrf-token' };
|
||||
|
||||
const { body } = await supertest
|
||||
.get(fleetSetupRouteService.getFleetSetupPath())
|
||||
.set(headers)
|
||||
.expect(200);
|
||||
|
||||
if (!body.isInitialized) {
|
||||
await supertest
|
||||
.post(setupRouteService.getSetupPath())
|
||||
.set(headers)
|
||||
.expect(200);
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export default function({ getService }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('Endpoint alert API without ingest manager initialized', () => {
|
||||
before(async () => {
|
||||
await esArchiver.load('endpoint/alerts/api_feature');
|
||||
await esArchiver.load('endpoint/alerts/host_api_feature');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await esArchiver.unload('endpoint/alerts/api_feature');
|
||||
await esArchiver.unload('endpoint/alerts/host_api_feature');
|
||||
});
|
||||
|
||||
it('should return a 500', async () => {
|
||||
await supertest.get('/api/endpoint/alerts').expect(500);
|
||||
});
|
||||
});
|
||||
}
|
16
x-pack/test/endpoint_api_integration_no_ingest/apis/index.ts
Normal file
16
x-pack/test/endpoint_api_integration_no_ingest/apis/index.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export default function endpointAPIIntegrationTests({ loadTestFile }: FtrProviderContext) {
|
||||
describe('Endpoint plugin', function() {
|
||||
this.tags('ciGroup7');
|
||||
loadTestFile(require.resolve('./index_pattern'));
|
||||
loadTestFile(require.resolve('./metadata'));
|
||||
loadTestFile(require.resolve('./alerts'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export default function({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
|
||||
describe('Endpoint index pattern API without ingest manager initialized', () => {
|
||||
it('should not retrieve the index pattern for events', async () => {
|
||||
await supertest.get('/api/endpoint/index_pattern/events').expect(404);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export default function({ getService }: FtrProviderContext) {
|
||||
const esArchiver = getService('esArchiver');
|
||||
const supertest = getService('supertest');
|
||||
describe('test metadata api when ingest manager is not initialized', () => {
|
||||
before(async () => await esArchiver.load('endpoint/metadata/api_feature'));
|
||||
after(async () => await esArchiver.unload('endpoint/metadata/api_feature'));
|
||||
it('metadata api should return a 500', async () => {
|
||||
await supertest
|
||||
.post('/api/endpoint/metadata')
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.send()
|
||||
.expect(500);
|
||||
});
|
||||
});
|
||||
}
|
19
x-pack/test/endpoint_api_integration_no_ingest/config.ts
Normal file
19
x-pack/test/endpoint_api_integration_no_ingest/config.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { FtrConfigProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
export default async function({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.js'));
|
||||
|
||||
return {
|
||||
...xPackAPITestsConfig.getAll(),
|
||||
testFiles: [require.resolve('./apis')],
|
||||
junit: {
|
||||
reportName: 'X-Pack Endpoint API Integration Without Ingest Tests',
|
||||
},
|
||||
};
|
||||
}
|
11
x-pack/test/endpoint_api_integration_no_ingest/ftr_provider_context.d.ts
vendored
Normal file
11
x-pack/test/endpoint_api_integration_no_ingest/ftr_provider_context.d.ts
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { GenericFtrProviderContext } from '@kbn/test/types/ftr';
|
||||
|
||||
import { services } from '../api_integration/services';
|
||||
|
||||
export type FtrProviderContext = GenericFtrProviderContext<typeof services, {}>;
|
Binary file not shown.
|
@ -1,33 +1,62 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"aliases": {
|
||||
},
|
||||
"index": "endpoint-agent-1",
|
||||
"aliases": {},
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"mappings": {
|
||||
"_meta": {
|
||||
"version": "1.5.0-dev"
|
||||
},
|
||||
"date_detection": false,
|
||||
"dynamic_templates": [
|
||||
{
|
||||
"strings_as_keyword": {
|
||||
"mapping": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"match_mapping_type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"@timestamp": {
|
||||
"type": "long"
|
||||
"type": "date"
|
||||
},
|
||||
"elastic": {
|
||||
"properties": {
|
||||
"agent": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"agent": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"version": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ecs": {
|
||||
"properties": {
|
||||
"version": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -36,109 +65,71 @@
|
|||
"policy": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
},
|
||||
"name": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"properties": {
|
||||
"created": {
|
||||
"type": "long"
|
||||
"type": "date"
|
||||
}
|
||||
}
|
||||
},
|
||||
"host": {
|
||||
"properties": {
|
||||
"architecture": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"hostname": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"id": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"ip": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"type": "ip"
|
||||
},
|
||||
"mac": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"os": {
|
||||
"properties": {
|
||||
"full": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
"text": {
|
||||
"norms": false,
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
"text": {
|
||||
"norms": false,
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"variant": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"version": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,11 +137,16 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"order": 1,
|
||||
"settings": {
|
||||
"index": {
|
||||
"number_of_replicas": "1",
|
||||
"number_of_shards": "1"
|
||||
"mapping": {
|
||||
"total_fields": {
|
||||
"limit": 10000
|
||||
}
|
||||
},
|
||||
"refresh_interval": "5s"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "3KVN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579881969541,
|
||||
"agent": {
|
||||
|
@ -51,7 +51,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "3aVN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579881969541,
|
||||
"agent": {
|
||||
|
@ -99,7 +99,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "3qVN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579881969541,
|
||||
"agent": {
|
||||
|
@ -145,7 +145,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "36VN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579878369541,
|
||||
"agent": {
|
||||
|
@ -194,7 +194,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "4KVN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579878369541,
|
||||
"agent": {
|
||||
|
@ -241,7 +241,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "4aVN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579878369541,
|
||||
"agent": {
|
||||
|
@ -288,7 +288,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "4qVN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579874769541,
|
||||
"agent": {
|
||||
|
@ -336,7 +336,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "46VN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579874769541,
|
||||
"agent": {
|
||||
|
@ -383,7 +383,7 @@
|
|||
"type": "doc",
|
||||
"value": {
|
||||
"id": "5KVN2G8BYQH1gtPUuYk7",
|
||||
"index": "endpoint-agent-1",
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"source": {
|
||||
"@timestamp": 1579874769541,
|
||||
"agent": {
|
||||
|
|
|
@ -1,50 +1,62 @@
|
|||
{
|
||||
"type": "index",
|
||||
"value": {
|
||||
"aliases": {
|
||||
},
|
||||
"index": "endpoint-agent-1",
|
||||
"aliases": {},
|
||||
"index": "metrics-endpoint-default-1",
|
||||
"mappings": {
|
||||
"_meta": {
|
||||
"version": "1.5.0-dev"
|
||||
},
|
||||
"date_detection": false,
|
||||
"dynamic_templates": [
|
||||
{
|
||||
"strings_as_keyword": {
|
||||
"mapping": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"match_mapping_type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"properties": {
|
||||
"@timestamp": {
|
||||
"type": "long"
|
||||
"type": "date"
|
||||
},
|
||||
"elastic": {
|
||||
"properties": {
|
||||
"agent": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"agent": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"version": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ecs": {
|
||||
"properties": {
|
||||
"version": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -53,109 +65,71 @@
|
|||
"policy": {
|
||||
"properties": {
|
||||
"id": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
},
|
||||
"name": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"properties": {
|
||||
"created": {
|
||||
"type": "long"
|
||||
"type": "date"
|
||||
}
|
||||
}
|
||||
},
|
||||
"host": {
|
||||
"properties": {
|
||||
"architecture": {
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"hostname": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"id": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"ip": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"type": "ip"
|
||||
},
|
||||
"mac": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"os": {
|
||||
"properties": {
|
||||
"full": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
"text": {
|
||||
"norms": false,
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"name": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
"text": {
|
||||
"norms": false,
|
||||
"type": "text"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"variant": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
},
|
||||
"version": {
|
||||
"fields": {
|
||||
"keyword": {
|
||||
"ignore_above": 256,
|
||||
"type": "keyword"
|
||||
}
|
||||
},
|
||||
"type": "text"
|
||||
"ignore_above": 1024,
|
||||
"type": "keyword"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,10 +137,15 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"order": 1,
|
||||
"settings": {
|
||||
"index": {
|
||||
"number_of_replicas": "1",
|
||||
"number_of_shards": "1"
|
||||
"mapping": {
|
||||
"total_fields": {
|
||||
"limit": 10000
|
||||
}
|
||||
},
|
||||
"refresh_interval": "5s"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ export default async function({ readConfigFile }: FtrConfigProviderContext) {
|
|||
...xpackFunctionalConfig.get('kbnTestServer.serverArgs'),
|
||||
'--xpack.endpoint.enabled=true',
|
||||
'--xpack.ingestManager.enabled=true',
|
||||
'--xpack.ingestManager.epm.enabled=true',
|
||||
'--xpack.ingestManager.fleet.enabled=true',
|
||||
],
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue