diff --git a/.buildkite/ftr_oblt_serverless_configs.yml b/.buildkite/ftr_oblt_serverless_configs.yml
index 9534e62926f06..085c25f2d80a6 100644
--- a/.buildkite/ftr_oblt_serverless_configs.yml
+++ b/.buildkite/ftr_oblt_serverless_configs.yml
@@ -1,5 +1,6 @@
disabled:
# Base config files, only necessary to inform config finding script
+ - x-pack/test_serverless/functional/test_suites/observability/cypress/oblt_config.base.ts
# Cypress configs, for now these are still run manually
- x-pack/test_serverless/functional/test_suites/observability/cypress/config_headless.ts
diff --git a/.buildkite/ftr_oblt_stateful_configs.yml b/.buildkite/ftr_oblt_stateful_configs.yml
index 7cecfd5e8d665..4edf75f385816 100644
--- a/.buildkite/ftr_oblt_stateful_configs.yml
+++ b/.buildkite/ftr_oblt_stateful_configs.yml
@@ -10,6 +10,9 @@ disabled:
- x-pack/plugins/observability_solution/profiling/e2e/ftr_config_runner.ts
- x-pack/plugins/observability_solution/profiling/e2e/ftr_config.ts
+ #FTR configs
+ - x-pack/plugins/observability_solution/uptime/e2e/config.ts
+
# Elastic Synthetics configs
- x-pack/plugins/observability_solution/uptime/e2e/uptime/synthetics_run.ts
- x-pack/plugins/observability_solution/synthetics/e2e/config.ts
@@ -27,6 +30,10 @@ enabled:
- x-pack/test/api_integration/apis/synthetics/config.ts
- x-pack/test/api_integration/apis/slos/config.ts
- x-pack/test/api_integration/apis/uptime/config.ts
+ - x-pack/test/apm_api_integration/basic/config.ts
+ - x-pack/test/apm_api_integration/cloud/config.ts
+ - x-pack/test/apm_api_integration/rules/config.ts
+ - x-pack/test/apm_api_integration/trial/config.ts
- x-pack/test/dataset_quality_api_integration/basic/config.ts
- x-pack/test/functional/apps/observability_logs_explorer/config.ts
- x-pack/test/functional/apps/dataset_quality/config.ts
diff --git a/.buildkite/ftr_platform_stateful_configs.yml b/.buildkite/ftr_platform_stateful_configs.yml
index a0425f766f569..96c15cce513c6 100644
--- a/.buildkite/ftr_platform_stateful_configs.yml
+++ b/.buildkite/ftr_platform_stateful_configs.yml
@@ -8,6 +8,8 @@ disabled:
- x-pack/test/functional_with_es_ssl/config.base.ts
- x-pack/test/api_integration/config.ts
- x-pack/test/fleet_api_integration/config.base.ts
+ - x-pack/test/functional_basic/apps/ml/config.base.ts
+ - x-pack/test/functional_basic/apps/transform/config.base.ts
# QA suites that are run out-of-band
- x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js
diff --git a/.buildkite/ftr_security_serverless_configs.yml b/.buildkite/ftr_security_serverless_configs.yml
index 51e3eba941c6b..3880175623fdd 100644
--- a/.buildkite/ftr_security_serverless_configs.yml
+++ b/.buildkite/ftr_security_serverless_configs.yml
@@ -1,5 +1,7 @@
disabled:
# Base config files, only necessary to inform config finding script
+ - x-pack/test_serverless/functional/test_suites/security/cypress/security_config.base.ts
+ - x-pack/test_serverless/functional/test_suites/security/cypress/cypress.config.ts
- x-pack/test/security_solution_api_integration/config/serverless/config.base.ts
- x-pack/test/security_solution_api_integration/config/serverless/config.base.essentials.ts
- x-pack/test/security_solution_api_integration/config/serverless/config.base.edr_workflows.ts
diff --git a/.buildkite/ftr_security_stateful_configs.yml b/.buildkite/ftr_security_stateful_configs.yml
index 8f1605b363e3d..a7931bab0a68d 100644
--- a/.buildkite/ftr_security_stateful_configs.yml
+++ b/.buildkite/ftr_security_stateful_configs.yml
@@ -5,6 +5,7 @@ disabled:
- x-pack/test/security_solution_api_integration/config/ess/config.base.edr_workflows.trial.ts
- x-pack/test/security_solution_api_integration/config/ess/config.base.edr_workflows.ts
- x-pack/test/security_solution_api_integration/config/ess/config.base.basic.ts
+ - x-pack/test/security_solution_api_integration/config/ess/config.base.trial.ts
- x-pack/test/security_solution_endpoint/configs/config.base.ts
- x-pack/test/security_solution_endpoint/config.base.ts
- x-pack/test/security_solution_endpoint_api_int/config.base.ts
diff --git a/.buildkite/pipelines/pull_request/base.yml b/.buildkite/pipelines/pull_request/base.yml
index 8b57562c7a329..e5da8ce788e5b 100644
--- a/.buildkite/pipelines/pull_request/base.yml
+++ b/.buildkite/pipelines/pull_request/base.yml
@@ -14,7 +14,7 @@ steps:
preemptible: true
key: build
if: "build.env('KIBANA_BUILD_ID') == null || build.env('KIBANA_BUILD_ID') == ''"
- timeout_in_minutes: 60
+ timeout_in_minutes: 90
retry:
automatic:
- exit_status: '-1'
diff --git a/.buildkite/scripts/pipelines/pull_request/pipeline.ts b/.buildkite/scripts/pipelines/pull_request/pipeline.ts
index cd5d9aa470b3c..db6be6c6e83f7 100644
--- a/.buildkite/scripts/pipelines/pull_request/pipeline.ts
+++ b/.buildkite/scripts/pipelines/pull_request/pipeline.ts
@@ -6,12 +6,12 @@
* Side Public License, v 1.
*/
-import { execSync } from 'child_process';
import fs from 'fs';
import prConfigs from '../../../pull_requests.json';
import { areChangesSkippable, doAnyChangesMatch, getAgentImageConfig } from '#pipeline-utils';
const prConfig = prConfigs.jobs.find((job) => job.pipelineSlug === 'kibana-pull-request');
+const emptyStep = `steps: []`;
if (!prConfig) {
console.error(`'kibana-pull-request' pipeline not found in .buildkite/pull_requests.json`);
@@ -28,21 +28,16 @@ const getPipeline = (filename: string, removeSteps = true) => {
};
(async () => {
+ const pipeline: string[] = [];
+
try {
const skippable = await areChangesSkippable(SKIPPABLE_PR_MATCHERS, REQUIRED_PATHS);
if (skippable) {
- console.log('All changes in PR are skippable. Skipping CI.');
-
- // Since we skip everything, including post-build, we need to at least make sure the commit status gets set
- execSync('BUILD_SUCCESSFUL=true .buildkite/scripts/lifecycle/commit_status_complete.sh', {
- stdio: 'inherit',
- });
- process.exit(0);
+ console.log(emptyStep);
+ return;
}
- const pipeline = [];
-
pipeline.push(getAgentImageConfig({ returnYaml: true }));
pipeline.push(getPipeline('.buildkite/pipelines/pull_request/base.yml', false));
diff --git a/docs/management/connectors/action-types/gemini.asciidoc b/docs/management/connectors/action-types/gemini.asciidoc
index 3c835d981465c..610fb4ad48f15 100644
--- a/docs/management/connectors/action-types/gemini.asciidoc
+++ b/docs/management/connectors/action-types/gemini.asciidoc
@@ -56,7 +56,7 @@ Body:: A stringified JSON payload sent to the {gemini} invoke model API. Fo
body: JSON.stringify({
contents: [{
role: user,
- parts: [{ text: 'Write the first line of a story about a magic backpack.' }]
+ parts: [{ text: 'Hello world!' }]
}],
generation_config: {
temperature: 0,
diff --git a/oas_docs/bundle.json b/oas_docs/bundle.json
index 5ccacb4c8acfb..32cb7b7436e13 100644
--- a/oas_docs/bundle.json
+++ b/oas_docs/bundle.json
@@ -395,7 +395,8 @@
"description": "Kibana's operational status. A minimal response is sent for unauthorized users."
}
}
- }
+ },
+ "description": "Overall status is OK and Kibana should be functioning normally."
},
"503": {
"content": {
@@ -412,7 +413,8 @@
"description": "Kibana's operational status. A minimal response is sent for unauthorized users."
}
}
- }
+ },
+ "description": "Kibana or some of it's essential services are unavailable. Kibana may be degraded or unavailable."
}
},
"summary": "Get Kibana's current status",
diff --git a/oas_docs/bundle.serverless.json b/oas_docs/bundle.serverless.json
index 5ccacb4c8acfb..32cb7b7436e13 100644
--- a/oas_docs/bundle.serverless.json
+++ b/oas_docs/bundle.serverless.json
@@ -395,7 +395,8 @@
"description": "Kibana's operational status. A minimal response is sent for unauthorized users."
}
}
- }
+ },
+ "description": "Overall status is OK and Kibana should be functioning normally."
},
"503": {
"content": {
@@ -412,7 +413,8 @@
"description": "Kibana's operational status. A minimal response is sent for unauthorized users."
}
}
- }
+ },
+ "description": "Kibana or some of it's essential services are unavailable. Kibana may be degraded or unavailable."
}
},
"summary": "Get Kibana's current status",
diff --git a/packages/core/http/core-http-resources-server-internal/src/http_resources_service.test.mocks.ts b/packages/core/http/core-http-resources-server-internal/src/http_resources_service.test.mocks.ts
deleted file mode 100644
index 0d0c637a768df..0000000000000
--- a/packages/core/http/core-http-resources-server-internal/src/http_resources_service.test.mocks.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0 and the Server Side Public License, v 1; you may not use this file except
- * in compliance with, at your election, the Elastic License 2.0 or the Server
- * Side Public License, v 1.
- */
-
-export const getApmConfigMock = jest.fn();
-
-jest.doMock('./get_apm_config', () => ({
- getApmConfig: getApmConfigMock,
-}));
diff --git a/packages/core/http/core-http-resources-server-internal/src/http_resources_service.test.ts b/packages/core/http/core-http-resources-server-internal/src/http_resources_service.test.ts
index 481b0b694747a..acf8950d0d147 100644
--- a/packages/core/http/core-http-resources-server-internal/src/http_resources_service.test.ts
+++ b/packages/core/http/core-http-resources-server-internal/src/http_resources_service.test.ts
@@ -6,10 +6,7 @@
* Side Public License, v 1.
*/
-import { getApmConfigMock } from './http_resources_service.test.mocks';
-
import type { RouteConfig } from '@kbn/core-http-server';
-
import { mockCoreContext } from '@kbn/core-base-server-mocks';
import { httpServiceMock, httpServerMock } from '@kbn/core-http-server-mocks';
import { renderingServiceMock } from '@kbn/core-rendering-server-mocks';
@@ -29,11 +26,6 @@ describe('HttpResources service', () => {
let router: ReturnType;
const kibanaRequest = httpServerMock.createKibanaRequest();
const context = createCoreRequestHandlerContextMock();
- const apmConfig = { mockApmConfig: true };
-
- beforeEach(() => {
- getApmConfigMock.mockReturnValue(apmConfig);
- });
describe('#createRegistrar', () => {
beforeEach(() => {
@@ -93,9 +85,6 @@ describe('HttpResources service', () => {
},
{
isAnonymousPage: false,
- vars: {
- apmConfig,
- },
}
);
});
@@ -118,9 +107,6 @@ describe('HttpResources service', () => {
},
{
isAnonymousPage: true,
- vars: {
- apmConfig,
- },
}
);
});
diff --git a/packages/core/http/core-http-resources-server-internal/src/http_resources_service.ts b/packages/core/http/core-http-resources-server-internal/src/http_resources_service.ts
index a896d6b98542f..bb9320bc5cb48 100644
--- a/packages/core/http/core-http-resources-server-internal/src/http_resources_service.ts
+++ b/packages/core/http/core-http-resources-server-internal/src/http_resources_service.ts
@@ -33,8 +33,6 @@ import type {
import type { InternalHttpResourcesSetup } from './types';
-import { getApmConfig } from './get_apm_config';
-
/**
* @internal
*/
@@ -112,13 +110,9 @@ export class HttpResourcesService implements CoreService {
isConfigSchema(
(
validationSchemas as () => RouteValidatorRequestAndResponses
- )().response![200].body()
+ )().response![200].body!()
)
).toBe(true);
expect(
isConfigSchema(
(
validationSchemas as () => RouteValidatorRequestAndResponses
- )().response![404].body()
+ )().response![404].body!()
)
).toBe(true);
}
diff --git a/packages/core/http/core-http-router-server-internal/src/util.test.ts b/packages/core/http/core-http-router-server-internal/src/util.test.ts
index 8febff7b113f6..0f615d7b58603 100644
--- a/packages/core/http/core-http-router-server-internal/src/util.test.ts
+++ b/packages/core/http/core-http-router-server-internal/src/util.test.ts
@@ -21,6 +21,10 @@ describe('prepareResponseValidation', () => {
404: {
body: jest.fn(() => schema.string()),
},
+ 500: {
+ description: 'just a description',
+ body: undefined,
+ },
unsafe: {
body: true,
},
@@ -32,13 +36,15 @@ describe('prepareResponseValidation', () => {
expect(prepared).toEqual({
200: { body: expect.any(Function) },
404: { body: expect.any(Function) },
+ 500: { description: 'just a description', body: undefined },
unsafe: { body: true },
});
- [1, 2, 3].forEach(() => prepared[200].body());
- [1, 2, 3].forEach(() => prepared[404].body());
+ [1, 2, 3].forEach(() => prepared[200].body!());
+ [1, 2, 3].forEach(() => prepared[404].body!());
expect(validation.response![200].body).toHaveBeenCalledTimes(1);
expect(validation.response![404].body).toHaveBeenCalledTimes(1);
+ expect(validation.response![500].body).toBeUndefined();
});
});
diff --git a/packages/core/http/core-http-router-server-internal/src/util.ts b/packages/core/http/core-http-router-server-internal/src/util.ts
index 75c18854f842f..5f854e2ee1568 100644
--- a/packages/core/http/core-http-router-server-internal/src/util.ts
+++ b/packages/core/http/core-http-router-server-internal/src/util.ts
@@ -9,25 +9,22 @@
import { once } from 'lodash';
import {
isFullValidatorContainer,
+ type RouteValidatorFullConfigResponse,
type RouteConfig,
type RouteMethod,
type RouteValidator,
} from '@kbn/core-http-server';
-import type { ObjectType, Type } from '@kbn/config-schema';
-import type { ZodEsque } from '@kbn/zod';
function isStatusCode(key: string) {
return !isNaN(parseInt(key, 10));
}
-interface ResponseValidation {
- [statusCode: number]: { body: () => ObjectType | Type | ZodEsque };
-}
-
-export function prepareResponseValidation(validation: ResponseValidation): ResponseValidation {
+export function prepareResponseValidation(
+ validation: RouteValidatorFullConfigResponse
+): RouteValidatorFullConfigResponse {
const responses = Object.entries(validation).map(([key, value]) => {
if (isStatusCode(key)) {
- return [key, { body: once(value.body) }];
+ return [key, { ...value, ...(value.body ? { body: once(value.body) } : {}) }];
}
return [key, value];
});
diff --git a/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts b/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts
index 269d53cfd897c..db6efd97c6f6b 100644
--- a/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts
+++ b/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.test.ts
@@ -241,12 +241,12 @@ describe('Versioned route', () => {
] = route.handlers;
const res200 = (validate as () => VersionedRouteValidation)()
- .response![200].body;
+ .response![200].body!;
expect(isConfigSchema(unwrapVersionedResponseBodyValidation(res200))).toBe(true);
const res404 = (validate as () => VersionedRouteValidation)()
- .response![404].body;
+ .response![404].body!;
expect(isConfigSchema(unwrapVersionedResponseBodyValidation(res404))).toBe(true);
@@ -301,6 +301,33 @@ describe('Versioned route', () => {
expect(validateOutputFn).toHaveBeenCalledTimes(1);
});
+ it('handles "undefined" response schemas', async () => {
+ let handler: RequestHandler;
+
+ (router.post as jest.Mock).mockImplementation((opts: unknown, fn) => (handler = fn));
+ const versionedRouter = CoreVersionedRouter.from({ router, isDev: true });
+ versionedRouter.post({ path: '/test/{id}', access: 'internal' }).addVersion(
+ {
+ version: '1',
+ validate: { response: { 500: { description: 'jest description', body: undefined } } },
+ },
+ async (ctx, req, res) => res.custom({ statusCode: 500 })
+ );
+
+ await expect(
+ handler!(
+ {} as any,
+ createRequest({
+ version: '1',
+ body: { foo: 1 },
+ params: { foo: 1 },
+ query: { foo: 1 },
+ }),
+ responseFactory
+ )
+ ).resolves.not.toThrow();
+ });
+
it('runs custom response validations', async () => {
let handler: RequestHandler;
const { fooValidation, validateBodyFn, validateOutputFn, validateParamsFn, validateQueryFn } =
diff --git a/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.ts b/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.ts
index b6192dbe68a25..ea69a25e4b56a 100644
--- a/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.ts
+++ b/packages/core/http/core-http-router-server-internal/src/versioned_router/core_versioned_route.ts
@@ -191,13 +191,13 @@ export class CoreVersionedRoute implements VersionedRoute {
const response = await handler.fn(ctx, req, res);
- if (this.router.isDev && validation?.response?.[response.status]) {
+ if (this.router.isDev && validation?.response?.[response.status]?.body) {
const { [response.status]: responseValidation, unsafe } = validation.response;
try {
validate(
{ body: response.payload },
{
- body: unwrapVersionedResponseBodyValidation(responseValidation.body),
+ body: unwrapVersionedResponseBodyValidation(responseValidation.body!),
unsafe: { body: unsafe?.body },
}
);
diff --git a/packages/core/http/core-http-router-server-internal/src/versioned_router/util.test.ts b/packages/core/http/core-http-router-server-internal/src/versioned_router/util.test.ts
index b9ef74c11fa3c..ae9409fcffb9b 100644
--- a/packages/core/http/core-http-router-server-internal/src/versioned_router/util.test.ts
+++ b/packages/core/http/core-http-router-server-internal/src/versioned_router/util.test.ts
@@ -7,8 +7,12 @@
*/
import { schema } from '@kbn/config-schema';
-import { VersionedRouteResponseValidation } from '@kbn/core-http-server';
-import { isCustomValidation, unwrapVersionedResponseBodyValidation } from './util';
+import type { VersionedRouteResponseValidation } from '@kbn/core-http-server';
+import {
+ isCustomValidation,
+ unwrapVersionedResponseBodyValidation,
+ prepareVersionedRouteValidation,
+} from './util';
test.each([
[() => schema.object({}), false],
@@ -17,6 +21,43 @@ test.each([
expect(isCustomValidation(input)).toBe(result);
});
+describe('prepareVersionedRouteValidation', () => {
+ it('wraps only expected values', () => {
+ const validate = {
+ request: {},
+ response: {
+ 200: {
+ body: jest.fn(() => schema.string()),
+ },
+ 404: {
+ body: jest.fn(() => schema.string()),
+ },
+ 500: {
+ description: 'just a description',
+ body: undefined,
+ },
+ },
+ };
+
+ const prepared = prepareVersionedRouteValidation({
+ version: '1',
+ validate,
+ });
+
+ expect(prepared).toEqual({
+ version: '1',
+ validate: {
+ request: {},
+ response: {
+ 200: { body: expect.any(Function) },
+ 404: { body: expect.any(Function) },
+ 500: { description: 'just a description', body: undefined },
+ },
+ },
+ });
+ });
+});
+
test('unwrapVersionedResponseBodyValidation', () => {
const mySchema = schema.object({});
const custom = () => ({ value: 'ok' });
@@ -29,6 +70,6 @@ test('unwrapVersionedResponseBodyValidation', () => {
},
};
- expect(unwrapVersionedResponseBodyValidation(validation[200].body)).toBe(mySchema);
- expect(unwrapVersionedResponseBodyValidation(validation[404].body)).toBe(custom);
+ expect(unwrapVersionedResponseBodyValidation(validation[200].body!)).toBe(mySchema);
+ expect(unwrapVersionedResponseBodyValidation(validation[404].body!)).toBe(custom);
});
diff --git a/packages/core/http/core-http-router-server-internal/src/versioned_router/util.ts b/packages/core/http/core-http-router-server-internal/src/versioned_router/util.ts
index ddd546be5bab5..88dad4eb50558 100644
--- a/packages/core/http/core-http-router-server-internal/src/versioned_router/util.ts
+++ b/packages/core/http/core-http-router-server-internal/src/versioned_router/util.ts
@@ -30,7 +30,7 @@ export function isCustomValidation(
* @internal
*/
export function unwrapVersionedResponseBodyValidation(
- validation: VersionedRouteResponseValidation[number]['body']
+ validation: VersionedResponseBodyValidation
): RouteValidationSpec {
if (isCustomValidation(validation)) {
return validation.custom;
@@ -43,8 +43,15 @@ function prepareValidation(validation: VersionedRouteValidation = RouteValidatorConfig {
}).toThrowError();
});
});
-
-describe('setup.getInjectedVar()', () => {
- it('returns values from injectedMetadata.vars', () => {
- const setup = new InjectedMetadataService({
- injectedMetadata: {
- vars: {
- foo: {
- bar: '1',
- },
- 'baz:box': {
- foo: 2,
- },
- },
- },
- } as any).setup();
-
- expect(setup.getInjectedVar('foo')).toEqual({
- bar: '1',
- });
- expect(setup.getInjectedVar('foo.bar')).toBe('1');
- expect(setup.getInjectedVar('baz:box')).toEqual({
- foo: 2,
- });
- expect(setup.getInjectedVar('')).toBe(undefined);
- });
-
- it('returns read-only values', () => {
- const setup = new InjectedMetadataService({
- injectedMetadata: {
- vars: {
- foo: {
- bar: 1,
- },
- },
- },
- } as any).setup();
-
- const foo: any = setup.getInjectedVar('foo');
- expect(() => {
- foo.bar = 2;
- }).toThrowErrorMatchingInlineSnapshot(
- `"Cannot assign to read only property 'bar' of object '#
+
-
-
+ {
+ application.navigateToUrl(http.basePath.prepend(`${VECTOR_SEARCH_PLUGIN.URL}`));
+ }}
>
-
- {i18n.translate(
- 'xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.buttonLabel',
- {
- defaultMessage: 'View trained models',
- }
- )}
+
+ {i18n.translate('xpack.enterpriseSearch.aiSearch.vectorSearchPanel.buttonLabel', {
+ defaultMessage: 'Set up Vector Search',
+ })}
-
+
- ),
- status: 'incomplete',
- },
- {
- title: i18n.translate('xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step2.title', {
- defaultMessage: 'Create an index',
- }),
- children: (
-
-
- {i18n.translate('xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step2.buttonLabel', {
- defaultMessage: 'Create an index',
- })}
-
-
- ),
- status: 'incomplete',
- },
- {
- title: i18n.translate('xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.title', {
- defaultMessage: 'Create a ML inference pipeline',
- }),
- children: (
-
-
-
- "
- {i18n.translate(
- 'xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.description.pipelinesName',
- {
- defaultMessage: 'Pipelines',
- }
- )}
- "
-
- ),
- }}
- />
-
-
- ),
- status: 'incomplete',
- },
-];
-
-export const VectorSearchPanel: React.FC = () => (
- <>
-
-
-
-
-
-
- {i18n.translate(
- 'xpack.enterpriseSearch.aiSearch.vectorSearchPanel.description.vectorDbCapabilitiesLinkText',
- {
- defaultMessage: "Elasticsearch's vector DB capabilities",
- }
- )}
-
- ),
- }}
- />
-
-
-
-
-
-
-
- >
-);
+ >
+ );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/layout/page_template.tsx b/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/layout/page_template.tsx
new file mode 100644
index 0000000000000..72ddbffc263c7
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/layout/page_template.tsx
@@ -0,0 +1,38 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { SEARCH_PRODUCT_NAME } from '../../../../../common/constants';
+import { SetSemanticSearchChrome } from '../../../shared/kibana_chrome';
+import {
+ EnterpriseSearchPageTemplateWrapper,
+ PageTemplateProps,
+ useEnterpriseSearchNav,
+} from '../../../shared/layout';
+import { SendEnterpriseSearchTelemetry } from '../../../shared/telemetry';
+
+export const EnterpriseSearchSemanticSearchPageTemplate: React.FC = ({
+ children,
+ pageChrome,
+ pageViewTelemetry,
+ ...pageTemplateProps
+}) => (
+ }
+ >
+ {pageViewTelemetry && (
+
+ )}
+ {children}
+
+);
diff --git a/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/semantic_search_guide/semantic_search_guide.scss b/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/semantic_search_guide/semantic_search_guide.scss
new file mode 100644
index 0000000000000..15fb1b242ac76
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/semantic_search_guide/semantic_search_guide.scss
@@ -0,0 +1,6 @@
+.chooseEmbeddingModelSelectedBorder {
+ border: 1px solid $euiColorPrimary;
+}
+.chooseEmbeddingModelBorder {
+ border: 1px solid $euiColorLightShade;
+}
diff --git a/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/semantic_search_guide/semantic_search_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/semantic_search_guide/semantic_search_guide.tsx
new file mode 100644
index 0000000000000..1b373da7a9ff2
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/semantic_search/components/semantic_search_guide/semantic_search_guide.tsx
@@ -0,0 +1,360 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+
+import { useSearchParams } from 'react-router-dom-v5-compat';
+
+import {
+ EuiCard,
+ EuiCode,
+ EuiFlexGrid,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiHorizontalRule,
+ EuiLink,
+ EuiSpacer,
+ EuiText,
+ EuiTitle,
+} from '@elastic/eui';
+import { i18n } from '@kbn/i18n';
+import { FormattedMessage } from '@kbn/i18n-react';
+
+import { SetAISearchChromeSearchDocsSection } from '../../../ai_search/components/ai_search_guide/ai_search_docs_section';
+import { docLinks } from '../../../shared/doc_links';
+import { SetSemanticSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
+import { DevToolsConsoleCodeBlock } from '../../../vector_search/components/dev_tools_console_code_block/dev_tools_console_code_block';
+import './semantic_search_guide.scss';
+import { EnterpriseSearchSemanticSearchPageTemplate } from '../layout/page_template';
+
+const SETUP_INFERENCE_ENDPOINT_ELSER = `PUT _inference/sparse_embedding/my-inference-endpoint
+{
+ "service": "elser",
+ "service_settings": {
+ "num_allocations": 1,
+ "num_threads": 1
+ }
+}
+`;
+
+const SETUP_INFERENCE_ENDPOINT_E5 = `PUT _inference/text_embedding/my-inference-endpoint
+{
+ "service": "elasticsearch",
+ "service_settings": {
+ "model_id": ".multilingual-e5-small",
+ "num_allocations": 1,
+ "num_threads": 1
+ }
+}
+`;
+
+const SETUP_INFERENCE_ENDPOINT_OPENAI = `PUT _inference/text_embedding/my-inference-endpoint
+{
+ "service": "openai",
+ "service_settings": {
+ "model_id": "text-embedding-3-small",
+ "api_key": "",
+ }
+}
+`;
+
+const SETUP_INFERENCE_ENDPOINT_BEDROCK = `PUT _inference/text_embedding/my-inference-endpoint
+{
+ "service": "amazonbedrock",
+ "service_settings": {
+ "access_key": "",
+ "secret_key": "",
+ "region": "us-east-1",
+ "provider": "amazontitan",
+ "model": "amazon.titan-embed-text-v2:0"
+ }
+}
+`;
+
+const CREATE_INDEX_SNIPPET = `PUT /my-index
+{
+ "mappings": {
+ "properties": {
+ "text": {
+ "type": "semantic_text",
+ "inference_id": "my-inference-endpoint"
+ }
+ }
+ }
+}`;
+
+const INGEST_SNIPPET = `POST /my-index/_doc
+{
+ "text": "There are a few foods and food groups that will help to fight inflammation and delayed onset muscle soreness (both things that are inevitable after a long, hard workout) when you incorporate them into your postworkout eats, whether immediately after your run or at a meal later in the day"
+}`;
+
+const QUERY_SNIPPET = `POST /my-index/_search
+{
+ "size" : 3,
+ "query" : {
+ "semantic": {
+ "field": "text",
+ "query": "How to avoid muscle soreness while running?"
+ }
+ }
+}`;
+
+const modelSelection: InferenceModel[] = [
+ {
+ id: 'elser',
+ modelName: 'ELSER',
+ code: SETUP_INFERENCE_ENDPOINT_ELSER,
+ link: docLinks.elser,
+ description: "Elastic's proprietary, best-in-class sparse vector model for semantic search.",
+ },
+ {
+ id: 'e5',
+ modelName: 'E5 Multilingual',
+ code: SETUP_INFERENCE_ENDPOINT_E5,
+ link: docLinks.e5Model,
+ description: 'Try an optimized third party multilingual model.',
+ },
+ {
+ code: SETUP_INFERENCE_ENDPOINT_OPENAI,
+ id: 'openai',
+ modelName: 'OpenAI',
+ link: 'https://platform.openai.com/docs/guides/embeddings',
+ description: "Connect with OpenAI's embedding models.",
+ },
+ {
+ id: 'bedrock',
+ modelName: 'Amazon Bedrock',
+ code: SETUP_INFERENCE_ENDPOINT_BEDROCK,
+ link: 'https://docs.aws.amazon.com/bedrock/latest/userguide/titan-embedding-models.html',
+ description: "Use Amazon Bedrock's embedding models.",
+ },
+];
+
+interface SelectModelPanelProps {
+ isSelectedModel: boolean;
+ model: InferenceModel;
+ setSelectedModel: (model: InferenceModel) => void;
+}
+
+interface InferenceModel {
+ code: string;
+ id: string;
+ link: string;
+ modelName: string;
+ description: string;
+}
+
+const SelectModelPanel: React.FC = ({
+ model,
+ setSelectedModel,
+ isSelectedModel,
+}) => {
+ return (
+
+
+
+ {model.description}
+
+
+
+
+
+ >
+ }
+ display={isSelectedModel ? 'primary' : 'plain'}
+ onClick={() => setSelectedModel(model)}
+ titleSize="xs"
+ hasBorder
+ textAlign="left"
+ />
+
+ );
+};
+
+export const SemanticSearchGuide: React.FC = () => {
+ const [searchParams] = useSearchParams();
+ const chosenUrlModel =
+ modelSelection.find((model) => model.id === searchParams.get('model_example')) ||
+ modelSelection[0];
+ const [selectedModel, setSelectedModel] = React.useState(chosenUrlModel);
+
+ return (
+
+ {' '}
+
+
+
+
+ ),
+ pageTitle: (
+
+ ),
+ }}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {modelSelection.map((model) => (
+
+ ))}
+
+
+
+ {selectedModel.code}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ semantic_text }}
+ />
+
+
+
+
+ {CREATE_INDEX_SNIPPET}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {INGEST_SNIPPET}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {QUERY_SNIPPET}
+
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/semantic_search/index.tsx b/x-pack/plugins/enterprise_search/public/applications/semantic_search/index.tsx
new file mode 100644
index 0000000000000..f33142bae940c
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/semantic_search/index.tsx
@@ -0,0 +1,41 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+// switch is not available on shared-ux-router
+// eslint-disable-next-line no-restricted-imports
+import { Switch } from 'react-router-dom';
+
+import { Route } from '@kbn/shared-ux-router';
+
+import { isVersionMismatch } from '../../../common/is_version_mismatch';
+import { InitialAppData } from '../../../common/types';
+import { VersionMismatchPage } from '../shared/version_mismatch';
+
+import { SemanticSearchGuide } from './components/semantic_search_guide/semantic_search_guide';
+
+import { ROOT_PATH } from './routes';
+
+export const EnterpriseSearchSemanticSearch: React.FC = (props) => {
+ const { enterpriseSearchVersion, kibanaVersion } = props;
+ const incompatibleVersions = isVersionMismatch(enterpriseSearchVersion, kibanaVersion);
+
+ return (
+
+
+ {incompatibleVersions ? (
+
+ ) : (
+
+ )}
+
+
+ );
+};
diff --git a/x-pack/plugins/enterprise_search/public/applications/semantic_search/jest.config.js b/x-pack/plugins/enterprise_search/public/applications/semantic_search/jest.config.js
new file mode 100644
index 0000000000000..7711d9b97523f
--- /dev/null
+++ b/x-pack/plugins/enterprise_search/public/applications/semantic_search/jest.config.js
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+module.exports = {
+ preset: '@kbn/test',
+ rootDir: '../../../../../..',
+ roots: ['/x-pack/plugins/enterprise_search/public/applications/semantic_search'],
+ collectCoverage: true,
+ coverageReporters: ['text', 'html'],
+ collectCoverageFrom: [
+ '/x-pack/plugins/enterprise_search/public/applications/**/*.{ts,tsx}',
+ '!/x-pack/plugins/enterprise_search/public/*.ts',
+ '!/x-pack/plugins/enterprise_search/server/*.ts',
+ '!/x-pack/plugins/enterprise_search/public/applications/test_helpers/**/*.{ts,tsx}',
+ ],
+ coverageDirectory:
+ '/target/kibana-coverage/jest/x-pack/plugins/enterprise_search/public/applications/semantic_search',
+ modulePathIgnorePatterns: [
+ '/x-pack/plugins/enterprise_search/public/applications/app_search/cypress',
+ '/x-pack/plugins/enterprise_search/public/applications/workplace_search/cypress',
+ ],
+};
diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema_legacy/index.ts b/x-pack/plugins/enterprise_search/public/applications/semantic_search/routes.ts
similarity index 87%
rename from x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema_legacy/index.ts
rename to x-pack/plugins/enterprise_search/public/applications/semantic_search/routes.ts
index a112f6ca1b29f..d6b0b0a669281 100644
--- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema_legacy/index.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/semantic_search/routes.ts
@@ -5,4 +5,4 @@
* 2.0.
*/
-export * from './common_attributes';
+export const ROOT_PATH = '/';
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts
index 228321ef120c1..311043a442bc8 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/doc_links/doc_links.ts
@@ -103,6 +103,7 @@ class DocLinks {
public crawlerOverview: string;
public deployTrainedModels: string;
public documentLevelSecurity: string;
+ public e5Model: string;
public elasticsearchCreateIndex: string;
public elasticsearchGettingStarted: string;
public elasticsearchMapping: string;
@@ -114,6 +115,7 @@ class DocLinks {
public enterpriseSearchTroubleshootSetup: string;
public enterpriseSearchUsersAccess: string;
public indexApi: string;
+ public inferenceApiCreate: string;
public ingestionApis: string;
public ingestPipelines: string;
public kibanaSecurity: string;
@@ -138,6 +140,7 @@ class DocLinks {
public searchTemplates: string;
public searchUIAppSearch: string;
public searchUIElasticsearch: string;
+ public semanticTextField: string;
public start: string;
public supportedNlpModels: string;
public syncRules: string;
@@ -280,6 +283,7 @@ class DocLinks {
this.crawlerOverview = '';
this.deployTrainedModels = '';
this.documentLevelSecurity = '';
+ this.e5Model = '';
this.elasticsearchCreateIndex = '';
this.elasticsearchGettingStarted = '';
this.elasticsearchMapping = '';
@@ -291,6 +295,7 @@ class DocLinks {
this.enterpriseSearchTroubleshootSetup = '';
this.enterpriseSearchUsersAccess = '';
this.indexApi = '';
+ this.inferenceApiCreate = '';
this.ingestionApis = '';
this.ingestPipelines = '';
this.kibanaSecurity = '';
@@ -315,6 +320,7 @@ class DocLinks {
this.searchLabs = '';
this.searchLabsRepo = '';
this.searchTemplates = '';
+ this.semanticTextField = '';
this.start = '';
this.supportedNlpModels = '';
this.syncRules = '';
@@ -459,6 +465,7 @@ class DocLinks {
this.crawlerOverview = docLinks.links.enterpriseSearch.crawlerOverview;
this.deployTrainedModels = docLinks.links.enterpriseSearch.deployTrainedModels;
this.documentLevelSecurity = docLinks.links.enterpriseSearch.documentLevelSecurity;
+ this.e5Model = docLinks.links.enterpriseSearch.e5Model;
this.elasticsearchCreateIndex = docLinks.links.elasticsearch.createIndex;
this.elasticsearchGettingStarted = docLinks.links.elasticsearch.gettingStarted;
this.elasticsearchMapping = docLinks.links.elasticsearch.mapping;
@@ -470,6 +477,7 @@ class DocLinks {
this.enterpriseSearchTroubleshootSetup = docLinks.links.enterpriseSearch.troubleshootSetup;
this.enterpriseSearchUsersAccess = docLinks.links.enterpriseSearch.usersAccess;
this.indexApi = docLinks.links.enterpriseSearch.indexApi;
+ this.inferenceApiCreate = docLinks.links.enterpriseSearch.inferenceApiCreate;
this.ingestionApis = docLinks.links.enterpriseSearch.ingestionApis;
this.ingestPipelines = docLinks.links.enterpriseSearch.ingestPipelines;
this.kibanaSecurity = docLinks.links.kibana.xpackSecurity;
@@ -494,6 +502,7 @@ class DocLinks {
this.searchLabs = docLinks.links.enterpriseSearch.searchLabs;
this.searchLabsRepo = docLinks.links.enterpriseSearch.searchLabsRepo;
this.searchTemplates = docLinks.links.enterpriseSearch.searchTemplates;
+ this.semanticTextField = docLinks.links.enterpriseSearch.semanticTextField;
this.start = docLinks.links.enterpriseSearch.start;
this.supportedNlpModels = docLinks.links.enterpriseSearch.supportedNlpModels;
this.syncRules = docLinks.links.enterpriseSearch.syncRules;
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts
index 5798a48680d1f..40e2d2fb27476 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_breadcrumbs.ts
@@ -21,6 +21,7 @@ import {
SEARCH_PRODUCT_NAME,
VECTOR_SEARCH_PLUGIN,
WORKPLACE_SEARCH_PLUGIN,
+ SEMANTIC_SEARCH_PLUGIN,
} from '../../../../common/constants';
import { stripLeadingSlash } from '../../../../common/strip_slashes';
@@ -167,3 +168,6 @@ export const useAiSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
export const useVectorSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
useSearchBreadcrumbs([{ text: VECTOR_SEARCH_PLUGIN.NAV_TITLE, path: '/' }, ...breadcrumbs]);
+
+export const useSemanticSearchBreadcrumbs = (breadcrumbs: Breadcrumbs = []) =>
+ useSearchBreadcrumbs([{ text: SEMANTIC_SEARCH_PLUGIN.NAME, path: '/' }, ...breadcrumbs]);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts
index c9400393b057b..eaeb30f1540d0 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/generate_title.ts
@@ -12,6 +12,7 @@ import {
ENTERPRISE_SEARCH_CONTENT_PLUGIN,
SEARCH_EXPERIENCES_PLUGIN,
SEARCH_PRODUCT_NAME,
+ SEMANTIC_SEARCH_PLUGIN,
VECTOR_SEARCH_PLUGIN,
WORKPLACE_SEARCH_PLUGIN,
} from '../../../../common/constants';
@@ -55,5 +56,8 @@ export const aiSearchTitle = (page: Title = []) => generateTitle([...page, AI_SE
export const vectorSearchTitle = (page: Title = []) =>
generateTitle([...page, VECTOR_SEARCH_PLUGIN.NAME]);
+export const semanticSearchTitle = (page: Title = []) =>
+ generateTitle([...page, SEMANTIC_SEARCH_PLUGIN.NAME]);
+
export const enterpriseSearchContentTitle = (page: Title = []) =>
generateTitle([...page, ENTERPRISE_SEARCH_CONTENT_PLUGIN.NAME]);
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/index.ts b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/index.ts
index ae2151287b1d1..f9a6564ab5f28 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/index.ts
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/index.ts
@@ -16,5 +16,6 @@ export {
SetWorkplaceSearchChrome,
SetSearchExperiencesChrome,
SetEnterpriseSearchApplicationsChrome,
+ SetSemanticSearchChrome,
SetVectorSearchChrome,
} from './set_chrome';
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx
index ac85bd89b6ba9..8f7c71d1309c0 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/kibana_chrome/set_chrome.tsx
@@ -27,6 +27,7 @@ import {
BreadcrumbTrail,
useSearchExperiencesBreadcrumbs,
useVectorSearchBreadcrumbs,
+ useSemanticSearchBreadcrumbs,
} from './generate_breadcrumbs';
import {
aiSearchTitle,
@@ -36,6 +37,7 @@ import {
enterpriseSearchContentTitle,
searchExperiencesTitle,
searchTitle,
+ semanticSearchTitle,
vectorSearchTitle,
workplaceSearchTitle,
} from './generate_title';
@@ -242,5 +244,21 @@ export const SetVectorSearchChrome: React.FC = ({ trail = [] })
return null;
};
+export const SetSemanticSearchChrome: React.FC = ({ trail = [] }) => {
+ const { setBreadcrumbs, setDocTitle } = useValues(KibanaLogic);
+
+ const title = reverseArray(trail);
+ const docTitle = semanticSearchTitle(title);
+
+ const breadcrumbs = useSemanticSearchBreadcrumbs(useGenerateBreadcrumbs(trail));
+
+ useEffect(() => {
+ setBreadcrumbs(breadcrumbs);
+ setDocTitle(docTitle);
+ }, [trail]);
+
+ return null;
+};
+
// Small util - performantly reverses an array without mutating the original array
const reverseArray = (array: string[]) => array.slice().reverse();
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx
index f818dfb9141f3..b2c31ff4868bc 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.test.tsx
@@ -111,6 +111,12 @@ const baseNavItems = [
items: undefined,
name: 'Vector Search',
},
+ {
+ href: '/app/enterprise_search/semantic_search',
+ id: 'semanticSearch',
+ items: undefined,
+ name: 'Semantic Search',
+ },
{
href: '/app/enterprise_search/ai_search',
id: 'aiSearch',
diff --git a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx
index e39f0f0b71f29..d0f8a60f3472a 100644
--- a/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/shared/layout/nav.tsx
@@ -24,6 +24,7 @@ import {
VECTOR_SEARCH_PLUGIN,
WORKPLACE_SEARCH_PLUGIN,
INFERENCE_ENDPOINTS_PLUGIN,
+ SEMANTIC_SEARCH_PLUGIN,
} from '../../../../common/constants';
import {
SEARCH_APPLICATIONS_PATH,
@@ -204,6 +205,14 @@ export const useEnterpriseSearchNav = (alwaysReturn = false) => {
to: VECTOR_SEARCH_PLUGIN.URL,
}),
},
+ {
+ id: 'semanticSearch',
+ name: SEMANTIC_SEARCH_PLUGIN.NAME,
+ ...generateNavLink({
+ shouldNotCreateHref: true,
+ to: SEMANTIC_SEARCH_PLUGIN.URL,
+ }),
+ },
{
id: 'aiSearch',
name: i18n.translate('xpack.enterpriseSearch.nav.aiSearchTitle', {
diff --git a/x-pack/plugins/enterprise_search/public/applications/vector_search/components/vector_search_guide/vector_search_guide.tsx b/x-pack/plugins/enterprise_search/public/applications/vector_search/components/vector_search_guide/vector_search_guide.tsx
index 3ee0453067747..0cf9cb753c26a 100644
--- a/x-pack/plugins/enterprise_search/public/applications/vector_search/components/vector_search_guide/vector_search_guide.tsx
+++ b/x-pack/plugins/enterprise_search/public/applications/vector_search/components/vector_search_guide/vector_search_guide.tsx
@@ -17,66 +17,56 @@ import {
EuiHorizontalRule,
EuiIcon,
EuiLink,
+ EuiSpacer,
EuiText,
EuiTitle,
} from '@elastic/eui';
import { FormattedMessage } from '@kbn/i18n-react';
-import { AI_SEARCH_PLUGIN } from '../../../../../common/constants';
+import { SEMANTIC_SEARCH_PLUGIN } from '../../../../../common/constants';
import elserIllustration from '../../../../assets/images/elser.svg';
import nlpIllustration from '../../../../assets/images/nlp.svg';
import { docLinks } from '../../../shared/doc_links';
+import { HttpLogic } from '../../../shared/http';
import { KibanaLogic } from '../../../shared/kibana';
import { SetVectorSearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { DevToolsConsoleCodeBlock } from '../dev_tools_console_code_block/dev_tools_console_code_block';
import { EnterpriseSearchVectorSearchPageTemplate } from '../layout/page_template';
-const CREATE_INDEX_SNIPPET = `PUT /image-index
+const CREATE_INDEX_SNIPPET = `PUT /my-index
{
"mappings": {
"properties": {
- "image-vector": {
+ "vector": {
"type": "dense_vector",
- "dims": 3,
- "index": true,
- "similarity": "l2_norm"
+ "dims": 3
},
- "title-vector": {
- "type": "dense_vector",
- "dims": 5,
- "index": true,
- "similarity": "l2_norm"
- },
- "title": {
+ "text": {
"type": "text"
- },
- "file-type": {
- "type": "keyword"
}
}
}
}`;
-const INGEST_SNIPPET = `POST /image-index/_bulk?refresh=true
-{ "index": { "_id": "1" } }
-{ "image-vector": [1, 5, -20], "title-vector": [12, 50, -10, 0, 1], "title": "moose family", "file-type": "jpg" }
-{ "index": { "_id": "2" } }
-{ "image-vector": [42, 8, -15], "title-vector": [25, 1, 4, -12, 2], "title": "alpine lake", "file-type": "png" }
-{ "index": { "_id": "3" } }
-{ "image-vector": [15, 11, 23], "title-vector": [1, 5, 25, 50, 20], "title": "full moon", "file-type": "jpg" }`;
+const INGEST_SNIPPET = `POST /my-index/_doc
+{
+ "vector": [1, 5, -20],
+ "text": "hello world"
+}`;
-const QUERY_SNIPPET = `POST /image-index/_search
+const QUERY_SNIPPET = `POST /my-index/_search
{
- "knn": {
- "field": "image-vector",
- "query_vector": [-5, 9, -12],
- "k": 10,
- "num_candidates": 100
- },
- "fields": [ "title", "file-type" ]
+ "size" : 3,
+ "query" : {
+ "knn": {
+ "field": "vector",
+ "query_vector": [1, 5, -20]
+ }
+ }
}`;
export const VectorSearchGuide: React.FC = () => {
+ const { http } = useValues(HttpLogic);
const { application } = useValues(KibanaLogic);
return (
@@ -120,6 +110,7 @@ export const VectorSearchGuide: React.FC = () => {
/>
+
{
@@ -165,7 +156,7 @@ export const VectorSearchGuide: React.FC = () => {
@@ -189,7 +180,7 @@ export const VectorSearchGuide: React.FC = () => {
@@ -197,7 +188,7 @@ export const VectorSearchGuide: React.FC = () => {
@@ -205,16 +196,18 @@ export const VectorSearchGuide: React.FC = () => {
- application.navigateToApp(AI_SEARCH_PLUGIN.URL.replace(/^(?:\/app\/)?(.*)$/, '$1'))
- }
+ onClick={() => {
+ application.navigateToUrl(
+ http.basePath.prepend(`${SEMANTIC_SEARCH_PLUGIN.URL}?model_example=elser`)
+ );
+ }}
layout="horizontal"
titleSize="s"
icon={}
title={
}
description={
@@ -224,22 +217,26 @@ export const VectorSearchGuide: React.FC = () => {
/>
}
/>
+
{
+ application.navigateToUrl(
+ http.basePath.prepend(`${SEMANTIC_SEARCH_PLUGIN.URL}?model_example=e5`)
+ );
+ }}
layout="horizontal"
titleSize="s"
icon={}
title={
}
description={
}
/>
diff --git a/x-pack/plugins/enterprise_search/public/plugin.ts b/x-pack/plugins/enterprise_search/public/plugin.ts
index 552bb43fbd073..496ce1821c0d1 100644
--- a/x-pack/plugins/enterprise_search/public/plugin.ts
+++ b/x-pack/plugins/enterprise_search/public/plugin.ts
@@ -55,6 +55,7 @@ import {
VECTOR_SEARCH_PLUGIN,
WORKPLACE_SEARCH_PLUGIN,
INFERENCE_ENDPOINTS_PLUGIN,
+ SEMANTIC_SEARCH_PLUGIN,
} from '../common/constants';
import {
CreatIndexLocatorDefinition,
@@ -383,6 +384,27 @@ export class EnterpriseSearchPlugin implements Plugin {
title: VECTOR_SEARCH_PLUGIN.NAV_TITLE,
});
+ core.application.register({
+ appRoute: SEMANTIC_SEARCH_PLUGIN.URL,
+ category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
+ euiIconType: SEMANTIC_SEARCH_PLUGIN.LOGO,
+ id: SEMANTIC_SEARCH_PLUGIN.ID,
+ mount: async (params: AppMountParameters) => {
+ const kibanaDeps = await this.getKibanaDeps(core, params, cloud);
+ const { chrome, http } = kibanaDeps.core;
+ chrome.docTitle.change(SEMANTIC_SEARCH_PLUGIN.NAME);
+
+ this.getInitialData(http);
+ const pluginData = this.getPluginData();
+
+ const { renderApp } = await import('./applications');
+ const { EnterpriseSearchSemanticSearch } = await import('./applications/semantic_search');
+
+ return renderApp(EnterpriseSearchSemanticSearch, kibanaDeps, pluginData);
+ },
+ title: SEMANTIC_SEARCH_PLUGIN.NAV_TITLE,
+ });
+
core.application.register({
appRoute: AI_SEARCH_PLUGIN.URL,
category: DEFAULT_APP_CATEGORIES.enterpriseSearch,
diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts
index d5c917443654f..a03429729bf2f 100644
--- a/x-pack/plugins/enterprise_search/server/plugin.ts
+++ b/x-pack/plugins/enterprise_search/server/plugin.ts
@@ -229,6 +229,7 @@ export class EnterpriseSearchPlugin implements Plugin {
enterpriseSearchApplications: showEnterpriseSearch,
enterpriseSearchAISearch: showEnterpriseSearch,
enterpriseSearchVectorSearch: showEnterpriseSearch,
+ enterpriseSearchSemanticSearch: showEnterpriseSearch,
enterpriseSearchElasticsearch: showEnterpriseSearch,
appSearch: hasAppSearchAccess && config.canDeployEntSearch,
workplaceSearch: hasWorkplaceSearchAccess && config.canDeployEntSearch,
@@ -241,6 +242,7 @@ export class EnterpriseSearchPlugin implements Plugin {
enterpriseSearchApplications: showEnterpriseSearch,
enterpriseSearchAISearch: showEnterpriseSearch,
enterpriseSearchVectorSearch: showEnterpriseSearch,
+ enterpriseSearchSemanticSearch: showEnterpriseSearch,
enterpriseSearchElasticsearch: showEnterpriseSearch,
appSearch: hasAppSearchAccess && config.canDeployEntSearch,
workplaceSearch: hasWorkplaceSearchAccess && config.canDeployEntSearch,
diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx
index 197d64810c199..35fd048cc13cd 100644
--- a/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx
+++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agents/agent_details_page/components/agent_details/agent_details_overview.tsx
@@ -149,7 +149,7 @@ export const AgentDetailsOverviewSection: React.FunctionComponent<{
description: agent.last_checkin_message ? agent.last_checkin_message : '-',
},
{
- title: i18n.translate('xpack.fleet.agentDetails.hostIdLabel', {
+ title: i18n.translate('xpack.fleet.agentDetails.agentIdLabel', {
defaultMessage: 'Agent ID',
}),
description: agent.id,
@@ -197,6 +197,15 @@ export const AgentDetailsOverviewSection: React.FunctionComponent<{
? agent.local_metadata.host.hostname
: '-',
},
+ {
+ title: i18n.translate('xpack.fleet.agentDetails.hostIdLabel', {
+ defaultMessage: 'Host ID',
+ }),
+ description:
+ typeof agent.local_metadata?.host?.id === 'string'
+ ? agent.local_metadata.host.id
+ : '-',
+ },
{
title: i18n.translate('xpack.fleet.agentDetails.logLevel', {
defaultMessage: 'Logging level',
diff --git a/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.test.tsx b/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.test.tsx
index a239b12deb5be..0b34d4453b2f1 100644
--- a/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.test.tsx
+++ b/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.test.tsx
@@ -249,9 +249,9 @@ describe('dimension editor', () => {
userEvent.type(customPrefixTextbox, prefix);
};
return {
- settingNone: screen.getByTitle(/none/i),
- settingAuto: screen.getByTitle(/auto/i),
- settingCustom: screen.getByTitle(/custom/i),
+ settingNone: () => screen.getByTitle(/none/i),
+ settingAuto: () => screen.getByTitle(/auto/i),
+ settingCustom: () => screen.getByTitle(/custom/i),
customPrefixTextbox,
typePrefix,
...rtlRender,
@@ -266,6 +266,11 @@ describe('dimension editor', () => {
expect(screen.queryByTestId(SELECTORS.BREAKDOWN_EDITOR)).not.toBeInTheDocument();
});
+ it(`doesn't break when layer data is missing`, () => {
+ renderSecondaryMetricEditor({ frame: { activeData: { first: undefined } } });
+ expect(screen.getByTestId(SELECTORS.SECONDARY_METRIC_EDITOR)).toBeInTheDocument();
+ });
+
describe('metric prefix', () => {
const NONE_PREFIX = '';
const AUTO_PREFIX = undefined;
@@ -280,9 +285,9 @@ describe('dimension editor', () => {
state: localState,
});
- expect(settingAuto).toHaveAttribute('aria-pressed', 'true');
- expect(settingNone).toHaveAttribute('aria-pressed', 'false');
- expect(settingCustom).toHaveAttribute('aria-pressed', 'false');
+ expect(settingAuto()).toHaveAttribute('aria-pressed', 'true');
+ expect(settingNone()).toHaveAttribute('aria-pressed', 'false');
+ expect(settingCustom()).toHaveAttribute('aria-pressed', 'false');
expect(customPrefixTextbox).not.toBeInTheDocument();
});
@@ -290,9 +295,9 @@ describe('dimension editor', () => {
const { settingAuto, settingCustom, settingNone, customPrefixTextbox } =
renderSecondaryMetricEditor({ state: { ...localState, secondaryPrefix: NONE_PREFIX } });
- expect(settingNone).toHaveAttribute('aria-pressed', 'true');
- expect(settingAuto).toHaveAttribute('aria-pressed', 'false');
- expect(settingCustom).toHaveAttribute('aria-pressed', 'false');
+ expect(settingNone()).toHaveAttribute('aria-pressed', 'true');
+ expect(settingAuto()).toHaveAttribute('aria-pressed', 'false');
+ expect(settingCustom()).toHaveAttribute('aria-pressed', 'false');
expect(customPrefixTextbox).not.toBeInTheDocument();
});
@@ -301,9 +306,9 @@ describe('dimension editor', () => {
const { settingAuto, settingCustom, settingNone, customPrefixTextbox } =
renderSecondaryMetricEditor({ state: customPrefixState });
- expect(settingAuto).toHaveAttribute('aria-pressed', 'false');
- expect(settingNone).toHaveAttribute('aria-pressed', 'false');
- expect(settingCustom).toHaveAttribute('aria-pressed', 'true');
+ expect(settingAuto()).toHaveAttribute('aria-pressed', 'false');
+ expect(settingNone()).toHaveAttribute('aria-pressed', 'false');
+ expect(settingCustom()).toHaveAttribute('aria-pressed', 'true');
expect(customPrefixTextbox).toHaveValue(customPrefixState.secondaryPrefix);
});
@@ -316,12 +321,12 @@ describe('dimension editor', () => {
state: { ...localState, secondaryPrefix: customPrefix },
});
- userEvent.click(settingNone);
+ userEvent.click(settingNone());
expect(setState).toHaveBeenCalledWith(
expect.objectContaining({ secondaryPrefix: NONE_PREFIX })
);
- userEvent.click(settingAuto);
+ userEvent.click(settingAuto());
expect(setState).toHaveBeenCalledWith(
expect.objectContaining({ secondaryPrefix: AUTO_PREFIX })
);
diff --git a/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx b/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx
index f040c6dc86fa4..24248621c0982 100644
--- a/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx
+++ b/x-pack/plugins/lens/public/visualizations/metric/dimension_editor.tsx
@@ -131,7 +131,7 @@ function MaximumEditor({ setState, state, idPrefix }: SubProps) {
}
function SecondaryMetricEditor({ accessor, idPrefix, frame, layerId, setState, state }: SubProps) {
- const columnName = getColumnByAccessor(accessor, frame.activeData?.[layerId].columns)?.name;
+ const columnName = getColumnByAccessor(accessor, frame.activeData?.[layerId]?.columns)?.name;
const defaultPrefix = columnName || '';
return (
diff --git a/x-pack/plugins/observability_solution/entity_manager/common/constants_entities.ts b/x-pack/plugins/observability_solution/entity_manager/common/constants_entities.ts
index 28e9823c15620..633dfa2f9fd29 100644
--- a/x-pack/plugins/observability_solution/entity_manager/common/constants_entities.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/common/constants_entities.ts
@@ -18,8 +18,6 @@ export const ENTITY_EVENT_COMPONENT_TEMPLATE_V1 =
// History constants
export const ENTITY_HISTORY = 'history' as const;
-export const ENTITY_HISTORY_INDEX_TEMPLATE_V1 =
- `${ENTITY_BASE_PREFIX}_${ENTITY_SCHEMA_VERSION_V1}_${ENTITY_HISTORY}_index_template` as const;
export const ENTITY_HISTORY_BASE_COMPONENT_TEMPLATE_V1 =
`${ENTITY_BASE_PREFIX}_${ENTITY_SCHEMA_VERSION_V1}_${ENTITY_HISTORY}_base` as const;
export const ENTITY_HISTORY_PREFIX_V1 =
@@ -29,8 +27,6 @@ export const ENTITY_HISTORY_INDEX_PREFIX_V1 =
// Latest constants
export const ENTITY_LATEST = 'latest' as const;
-export const ENTITY_LATEST_INDEX_TEMPLATE_V1 =
- `${ENTITY_BASE_PREFIX}_${ENTITY_SCHEMA_VERSION_V1}_${ENTITY_LATEST}_index_template` as const;
export const ENTITY_LATEST_BASE_COMPONENT_TEMPLATE_V1 =
`${ENTITY_BASE_PREFIX}_${ENTITY_SCHEMA_VERSION_V1}_${ENTITY_LATEST}_base` as const;
export const ENTITY_LATEST_PREFIX_V1 =
diff --git a/x-pack/plugins/observability_solution/entity_manager/common/helpers.test.ts b/x-pack/plugins/observability_solution/entity_manager/common/helpers.test.ts
new file mode 100644
index 0000000000000..50ce0caeba0a3
--- /dev/null
+++ b/x-pack/plugins/observability_solution/entity_manager/common/helpers.test.ts
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { getEntityHistoryIndexTemplateV1, getEntityLatestIndexTemplateV1 } from './helpers';
+
+describe('helpers', () => {
+ it('getEntityHistoryIndexTemplateV1 should return the correct value', () => {
+ const definitionId = 'test';
+ const result = getEntityHistoryIndexTemplateV1(definitionId);
+ expect(result).toEqual('entities_v1_history_test_index_template');
+ });
+
+ it('getEntityLatestIndexTemplateV1 should return the correct value', () => {
+ const definitionId = 'test';
+ const result = getEntityLatestIndexTemplateV1(definitionId);
+ expect(result).toEqual('entities_v1_latest_test_index_template');
+ });
+});
diff --git a/x-pack/plugins/observability_solution/entity_manager/common/helpers.ts b/x-pack/plugins/observability_solution/entity_manager/common/helpers.ts
new file mode 100644
index 0000000000000..97a6317fee283
--- /dev/null
+++ b/x-pack/plugins/observability_solution/entity_manager/common/helpers.ts
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import {
+ ENTITY_BASE_PREFIX,
+ ENTITY_HISTORY,
+ ENTITY_LATEST,
+ ENTITY_SCHEMA_VERSION_V1,
+} from './constants_entities';
+
+export const getEntityHistoryIndexTemplateV1 = (definitionId: string) =>
+ `${ENTITY_BASE_PREFIX}_${ENTITY_SCHEMA_VERSION_V1}_${ENTITY_HISTORY}_${definitionId}_index_template` as const;
+
+export const getEntityLatestIndexTemplateV1 = (definitionId: string) =>
+ `${ENTITY_BASE_PREFIX}_${ENTITY_SCHEMA_VERSION_V1}_${ENTITY_LATEST}_${definitionId}_index_template` as const;
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/auth/privileges.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/auth/privileges.ts
index 00f09209fb3b6..3bc88127a5964 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/auth/privileges.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/auth/privileges.ts
@@ -21,7 +21,13 @@ export const requiredRunTimePrivileges = {
privileges: ['read', 'view_index_metadata'],
},
],
- cluster: ['manage_transform', 'monitor_transform', 'manage_ingest_pipelines', 'monitor'],
+ cluster: [
+ 'manage_transform',
+ 'monitor_transform',
+ 'manage_ingest_pipelines',
+ 'monitor',
+ 'manage_index_templates',
+ ],
application: [
{
application: 'kibana-.kibana',
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_history_processors.test.ts.snap b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_history_processors.test.ts.snap
index 925c62d97710f..9e62633a0a7d6 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_history_processors.test.ts.snap
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_history_processors.test.ts.snap
@@ -148,5 +148,29 @@ if (ctx.entity?.metadata?.sourceIndex != null) {
"index_name_prefix": ".entities.v1.history.admin-console-services.",
},
},
+ Object {
+ "pipeline": Object {
+ "ignore_missing_pipeline": true,
+ "name": "admin-console-services@platform",
+ },
+ },
+ Object {
+ "pipeline": Object {
+ "ignore_missing_pipeline": true,
+ "name": "admin-console-services-history@platform",
+ },
+ },
+ Object {
+ "pipeline": Object {
+ "ignore_missing_pipeline": true,
+ "name": "admin-console-services@custom",
+ },
+ },
+ Object {
+ "pipeline": Object {
+ "ignore_missing_pipeline": true,
+ "name": "admin-console-services-history@custom",
+ },
+ },
]
`;
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_latest_processors.test.ts.snap b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_latest_processors.test.ts.snap
index 69e63abd0cb94..e96d7366e7e04 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_latest_processors.test.ts.snap
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/__snapshots__/generate_latest_processors.test.ts.snap
@@ -108,5 +108,29 @@ ctx.event.category = ctx.entity.identity.event.category.keySet().toArray()[0];",
"value": ".entities.v1.latest.admin-console-services",
},
},
+ Object {
+ "pipeline": Object {
+ "ignore_missing_pipeline": true,
+ "name": "admin-console-services@platform",
+ },
+ },
+ Object {
+ "pipeline": Object {
+ "ignore_missing_pipeline": true,
+ "name": "admin-console-services-latest@platform",
+ },
+ },
+ Object {
+ "pipeline": Object {
+ "ignore_missing_pipeline": true,
+ "name": "admin-console-services@custom",
+ },
+ },
+ Object {
+ "pipeline": Object {
+ "ignore_missing_pipeline": true,
+ "name": "admin-console-services-latest@custom",
+ },
+ },
]
`;
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/generate_history_processors.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/generate_history_processors.ts
index 45ee008f9c6b5..43f18b2b81bf0 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/generate_history_processors.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/generate_history_processors.ts
@@ -163,5 +163,30 @@ export function generateHistoryProcessors(definition: EntityDefinition) {
date_formats: ['UNIX_MS', 'ISO8601', "yyyy-MM-dd'T'HH:mm:ss.SSSXX"],
},
},
+ {
+ pipeline: {
+ ignore_missing_pipeline: true,
+ name: `${definition.id}@platform`,
+ },
+ },
+ {
+ pipeline: {
+ ignore_missing_pipeline: true,
+ name: `${definition.id}-history@platform`,
+ },
+ },
+
+ {
+ pipeline: {
+ ignore_missing_pipeline: true,
+ name: `${definition.id}@custom`,
+ },
+ },
+ {
+ pipeline: {
+ ignore_missing_pipeline: true,
+ name: `${definition.id}-history@custom`,
+ },
+ },
];
}
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/generate_latest_processors.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/generate_latest_processors.ts
index 22b2ac19775a1..b9a18e8b7a2b6 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/generate_latest_processors.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/ingest_pipeline/generate_latest_processors.ts
@@ -122,5 +122,30 @@ export function generateLatestProcessors(definition: EntityDefinition) {
value: `${generateLatestIndexName(definition)}`,
},
},
+ {
+ pipeline: {
+ ignore_missing_pipeline: true,
+ name: `${definition.id}@platform`,
+ },
+ },
+ {
+ pipeline: {
+ ignore_missing_pipeline: true,
+ name: `${definition.id}-latest@platform`,
+ },
+ },
+ {
+ pipeline: {
+ ignore_missing_pipeline: true,
+ name: `${definition.id}@custom`,
+ },
+ },
+
+ {
+ pipeline: {
+ ignore_missing_pipeline: true,
+ name: `${definition.id}-latest@custom`,
+ },
+ },
];
}
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/install_entity_definition.test.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/install_entity_definition.test.ts
index 8560f0a4f1f4f..95eb63253f40c 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/install_entity_definition.test.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/install_entity_definition.test.ts
@@ -34,6 +34,18 @@ const assertHasCreatedDefinition = (
overwrite: true,
});
+ expect(esClient.indices.putIndexTemplate).toBeCalledTimes(2);
+ expect(esClient.indices.putIndexTemplate).toBeCalledWith(
+ expect.objectContaining({
+ name: `entities_v1_history_${definition.id}_index_template`,
+ })
+ );
+ expect(esClient.indices.putIndexTemplate).toBeCalledWith(
+ expect.objectContaining({
+ name: `entities_v1_latest_${definition.id}_index_template`,
+ })
+ );
+
expect(esClient.ingest.putPipeline).toBeCalledTimes(2);
expect(esClient.ingest.putPipeline).toBeCalledWith({
id: generateHistoryIngestPipelineId(builtInServicesFromLogsEntityDefinition),
@@ -111,6 +123,20 @@ const assertHasUninstalledDefinition = (
expect(esClient.transform.deleteTransform).toBeCalledTimes(2);
expect(esClient.ingest.deletePipeline).toBeCalledTimes(2);
expect(soClient.delete).toBeCalledTimes(1);
+
+ expect(esClient.indices.deleteIndexTemplate).toBeCalledTimes(2);
+ expect(esClient.indices.deleteIndexTemplate).toBeCalledWith(
+ {
+ name: `entities_v1_history_${definition.id}_index_template`,
+ },
+ { ignore: [404] }
+ );
+ expect(esClient.indices.deleteIndexTemplate).toBeCalledWith(
+ {
+ name: `entities_v1_latest_${definition.id}_index_template`,
+ },
+ { ignore: [404] }
+ );
};
describe('install_entity_definition', () => {
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/install_entity_definition.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/install_entity_definition.ts
index 980c743575fe2..b47f17b6b00fa 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/install_entity_definition.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/install_entity_definition.ts
@@ -9,6 +9,10 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import { EntityDefinition } from '@kbn/entities-schema';
import { Logger } from '@kbn/logging';
+import {
+ getEntityHistoryIndexTemplateV1,
+ getEntityLatestIndexTemplateV1,
+} from '../../../common/helpers';
import {
createAndInstallHistoryIngestPipeline,
createAndInstallLatestIngestPipeline,
@@ -28,6 +32,9 @@ import {
stopAndDeleteLatestTransform,
} from './stop_and_delete_transform';
import { uninstallEntityDefinition } from './uninstall_entity_definition';
+import { deleteTemplate, upsertTemplate } from '../manage_index_templates';
+import { getEntitiesLatestIndexTemplateConfig } from '../../templates/entities_latest_template';
+import { getEntitiesHistoryIndexTemplateConfig } from '../../templates/entities_history_template';
export interface InstallDefinitionParams {
esClient: ElasticsearchClient;
@@ -52,6 +59,10 @@ export async function installEntityDefinition({
latest: false,
},
definition: false,
+ indexTemplates: {
+ history: false,
+ latest: false,
+ },
};
try {
@@ -62,6 +73,20 @@ export async function installEntityDefinition({
const entityDefinition = await saveEntityDefinition(soClient, definition);
installState.definition = true;
+ // install scoped index template
+ await upsertTemplate({
+ esClient,
+ logger,
+ template: getEntitiesHistoryIndexTemplateConfig(definition.id),
+ });
+ installState.indexTemplates.history = true;
+ await upsertTemplate({
+ esClient,
+ logger,
+ template: getEntitiesLatestIndexTemplateConfig(definition.id),
+ });
+ installState.indexTemplates.latest = true;
+
// install ingest pipelines
logger.debug(`Installing ingest pipelines for definition ${definition.id}`);
await createAndInstallHistoryIngestPipeline(esClient, entityDefinition, logger);
@@ -99,6 +124,21 @@ export async function installEntityDefinition({
await stopAndDeleteLatestTransform(esClient, definition, logger);
}
+ if (installState.indexTemplates.history) {
+ await deleteTemplate({
+ esClient,
+ logger,
+ name: getEntityHistoryIndexTemplateV1(definition.id),
+ });
+ }
+ if (installState.indexTemplates.latest) {
+ await deleteTemplate({
+ esClient,
+ logger,
+ name: getEntityLatestIndexTemplateV1(definition.id),
+ });
+ }
+
throw e;
}
}
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/uninstall_entity_definition.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/uninstall_entity_definition.ts
index 8642ebafa904b..9b8685031642a 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/uninstall_entity_definition.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/entities/uninstall_entity_definition.ts
@@ -9,6 +9,10 @@ import { ElasticsearchClient } from '@kbn/core-elasticsearch-server';
import { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server';
import { EntityDefinition } from '@kbn/entities-schema';
import { Logger } from '@kbn/logging';
+import {
+ getEntityHistoryIndexTemplateV1,
+ getEntityLatestIndexTemplateV1,
+} from '../../../common/helpers';
import { deleteEntityDefinition } from './delete_entity_definition';
import { deleteIndices } from './delete_index';
import { deleteHistoryIngestPipeline, deleteLatestIngestPipeline } from './delete_ingest_pipeline';
@@ -17,6 +21,7 @@ import {
stopAndDeleteHistoryTransform,
stopAndDeleteLatestTransform,
} from './stop_and_delete_transform';
+import { deleteTemplate } from '../manage_index_templates';
export async function uninstallEntityDefinition({
definition,
@@ -36,6 +41,9 @@ export async function uninstallEntityDefinition({
await deleteHistoryIngestPipeline(esClient, definition, logger);
await deleteLatestIngestPipeline(esClient, definition, logger);
await deleteEntityDefinition(soClient, definition, logger);
+ await deleteTemplate({ esClient, logger, name: getEntityHistoryIndexTemplateV1(definition.id) });
+ await deleteTemplate({ esClient, logger, name: getEntityLatestIndexTemplateV1(definition.id) });
+
if (deleteData) {
await deleteIndices(esClient, definition, logger);
}
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/lib/manage_index_templates.ts b/x-pack/plugins/observability_solution/entity_manager/server/lib/manage_index_templates.ts
index 0f73ba7715bfd..f300df4a92c1d 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/lib/manage_index_templates.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/lib/manage_index_templates.ts
@@ -10,6 +10,7 @@ import {
IndicesPutIndexTemplateRequest,
} from '@elastic/elasticsearch/lib/api/types';
import { ElasticsearchClient, Logger } from '@kbn/core/server';
+import { retryTransientEsErrors } from './entities/helpers/retry';
interface TemplateManagementOptions {
esClient: ElasticsearchClient;
@@ -23,12 +24,18 @@ interface ComponentManagementOptions {
logger: Logger;
}
+interface DeleteTemplateOptions {
+ esClient: ElasticsearchClient;
+ name: string;
+ logger: Logger;
+}
+
export async function upsertTemplate({ esClient, template, logger }: TemplateManagementOptions) {
try {
- await esClient.indices.putIndexTemplate(template);
+ await retryTransientEsErrors(() => esClient.indices.putIndexTemplate(template), { logger });
} catch (error: any) {
logger.error(`Error updating entity manager index template: ${error.message}`);
- return;
+ throw error;
}
logger.info(
@@ -37,12 +44,26 @@ export async function upsertTemplate({ esClient, template, logger }: TemplateMan
logger.debug(() => `Entity manager index template: ${JSON.stringify(template)}`);
}
+export async function deleteTemplate({ esClient, name, logger }: DeleteTemplateOptions) {
+ try {
+ await retryTransientEsErrors(
+ () => esClient.indices.deleteIndexTemplate({ name }, { ignore: [404] }),
+ { logger }
+ );
+ } catch (error: any) {
+ logger.error(`Error deleting entity manager index template: ${error.message}`);
+ throw error;
+ }
+}
+
export async function upsertComponent({ esClient, component, logger }: ComponentManagementOptions) {
try {
- await esClient.cluster.putComponentTemplate(component);
+ await retryTransientEsErrors(() => esClient.cluster.putComponentTemplate(component), {
+ logger,
+ });
} catch (error: any) {
logger.error(`Error updating entity manager component template: ${error.message}`);
- return;
+ throw error;
}
logger.info(
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/plugin.ts b/x-pack/plugins/observability_solution/entity_manager/server/plugin.ts
index 3a51988841766..80154149e2402 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/plugin.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/plugin.ts
@@ -14,7 +14,7 @@ import {
PluginConfigDescriptor,
Logger,
} from '@kbn/core/server';
-import { upsertComponent, upsertTemplate } from './lib/manage_index_templates';
+import { upsertComponent } from './lib/manage_index_templates';
import { setupRoutes } from './routes';
import {
EntityManagerPluginSetupDependencies,
@@ -27,8 +27,6 @@ import { entityDefinition, EntityDiscoveryApiKeyType } from './saved_objects';
import { entitiesEntityComponentTemplateConfig } from './templates/components/entity';
import { entitiesLatestBaseComponentTemplateConfig } from './templates/components/base_latest';
import { entitiesHistoryBaseComponentTemplateConfig } from './templates/components/base_history';
-import { entitiesHistoryIndexTemplateConfig } from './templates/entities_history_template';
-import { entitiesLatestIndexTemplateConfig } from './templates/entities_latest_template';
export type EntityManagerServerPluginSetup = ReturnType;
export type EntityManagerServerPluginStart = ReturnType;
@@ -113,22 +111,7 @@ export class EntityManagerServerPlugin
logger: this.logger,
component: entitiesEntityComponentTemplateConfig,
}),
- ])
- .then(() =>
- upsertTemplate({
- esClient,
- logger: this.logger,
- template: entitiesHistoryIndexTemplateConfig,
- })
- )
- .then(() =>
- upsertTemplate({
- esClient,
- logger: this.logger,
- template: entitiesLatestIndexTemplateConfig,
- })
- )
- .catch(() => {});
+ ]).catch(() => {});
return {};
}
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/create.ts b/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/create.ts
index 8d17debc8914d..9d38cc7c5e716 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/create.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/create.ts
@@ -7,7 +7,7 @@
import { RequestHandlerContext } from '@kbn/core/server';
import { EntityDefinition, entityDefinitionSchema } from '@kbn/entities-schema';
-import { stringifyZodError } from '@kbn/zod-helpers';
+import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
import { SetupRouteOptions } from '../types';
import { EntityIdConflict } from '../../lib/entities/errors/entity_id_conflict_error';
import { EntitySecurityException } from '../../lib/entities/errors/entity_security_exception';
@@ -23,13 +23,7 @@ export function createEntityDefinitionRoute({
{
path: '/internal/entities/definition',
validate: {
- body: (body, res) => {
- try {
- return res.ok(entityDefinitionSchema.parse(body));
- } catch (e) {
- return res.badRequest(stringifyZodError(e));
- }
- },
+ body: buildRouteValidationWithZod(entityDefinitionSchema.strict()),
},
},
async (context, req, res) => {
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/delete.ts b/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/delete.ts
index f79fdce2368c6..b0c423a47a4b9 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/delete.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/delete.ts
@@ -6,7 +6,11 @@
*/
import { RequestHandlerContext } from '@kbn/core/server';
-import { schema } from '@kbn/config-schema';
+import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
+import {
+ deleteEntityDefinitionParamsSchema,
+ deleteEntityDefinitionQuerySchema,
+} from '@kbn/entities-schema';
import { SetupRouteOptions } from '../types';
import { EntitySecurityException } from '../../lib/entities/errors/entity_security_exception';
import { InvalidTransformError } from '../../lib/entities/errors/invalid_transform_error';
@@ -22,12 +26,8 @@ export function deleteEntityDefinitionRoute({
{
path: '/internal/entities/definition/{id}',
validate: {
- params: schema.object({
- id: schema.string(),
- }),
- query: schema.object({
- deleteData: schema.maybe(schema.boolean({ defaultValue: false })),
- }),
+ params: buildRouteValidationWithZod(deleteEntityDefinitionParamsSchema.strict()),
+ query: buildRouteValidationWithZod(deleteEntityDefinitionQuerySchema.strict()),
},
},
async (context, req, res) => {
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/get.ts b/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/get.ts
index 25a593c05209e..3f1ffde5afef4 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/get.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/get.ts
@@ -6,7 +6,8 @@
*/
import { RequestHandlerContext } from '@kbn/core/server';
-import { schema } from '@kbn/config-schema';
+import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
+import { getEntityDefinitionQuerySchema } from '@kbn/entities-schema';
import { SetupRouteOptions } from '../types';
import { findEntityDefinitions } from '../../lib/entities/find_entity_definition';
@@ -17,10 +18,7 @@ export function getEntityDefinitionRoute({
{
path: '/internal/entities/definition',
validate: {
- query: schema.object({
- page: schema.maybe(schema.number()),
- perPage: schema.maybe(schema.number()),
- }),
+ query: buildRouteValidationWithZod(getEntityDefinitionQuerySchema.strict()),
},
},
async (context, req, res) => {
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/reset.ts b/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/reset.ts
index ffa85931a3bef..6f97a5fbe0d51 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/reset.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/routes/entities/reset.ts
@@ -6,7 +6,8 @@
*/
import { RequestHandlerContext } from '@kbn/core/server';
-import { schema } from '@kbn/config-schema';
+import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
+import { resetEntityDefinitionParamsSchema } from '@kbn/entities-schema';
import { SetupRouteOptions } from '../types';
import { EntitySecurityException } from '../../lib/entities/errors/entity_security_exception';
import { InvalidTransformError } from '../../lib/entities/errors/invalid_transform_error';
@@ -39,9 +40,7 @@ export function resetEntityDefinitionRoute({
{
path: '/internal/entities/definition/{id}/_reset',
validate: {
- params: schema.object({
- id: schema.string(),
- }),
+ params: buildRouteValidationWithZod(resetEntityDefinitionParamsSchema.strict()),
},
},
async (context, req, res) => {
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/templates/components/helpers.test.ts b/x-pack/plugins/observability_solution/entity_manager/server/templates/components/helpers.test.ts
new file mode 100644
index 0000000000000..3321ee39edeb4
--- /dev/null
+++ b/x-pack/plugins/observability_solution/entity_manager/server/templates/components/helpers.test.ts
@@ -0,0 +1,32 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { getCustomHistoryTemplateComponents, getCustomLatestTemplateComponents } from './helpers';
+
+describe('helpers', () => {
+ it('getCustomLatestTemplateComponents should return template component in the right sort order', () => {
+ const definitionId = 'test';
+ const result = getCustomLatestTemplateComponents(definitionId);
+ expect(result).toEqual([
+ 'test@platform',
+ 'test-latest@platform',
+ 'test@custom',
+ 'test-latest@custom',
+ ]);
+ });
+
+ it('getCustomHistoryTemplateComponents should return template component in the right sort order', () => {
+ const definitionId = 'test';
+ const result = getCustomHistoryTemplateComponents(definitionId);
+ expect(result).toEqual([
+ 'test@platform',
+ 'test-history@platform',
+ 'test@custom',
+ 'test-history@custom',
+ ]);
+ });
+});
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/templates/components/helpers.ts b/x-pack/plugins/observability_solution/entity_manager/server/templates/components/helpers.ts
new file mode 100644
index 0000000000000..e976a216da97b
--- /dev/null
+++ b/x-pack/plugins/observability_solution/entity_manager/server/templates/components/helpers.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export const getCustomLatestTemplateComponents = (definitionId: string) => [
+ `${definitionId}@platform`, // @platform goes before so it can be overwritten by custom
+ `${definitionId}-latest@platform`,
+ `${definitionId}@custom`,
+ `${definitionId}-latest@custom`,
+];
+
+export const getCustomHistoryTemplateComponents = (definitionId: string) => [
+ `${definitionId}@platform`, // @platform goes before so it can be overwritten by custom
+ `${definitionId}-history@platform`,
+ `${definitionId}@custom`,
+ `${definitionId}-history@custom`,
+];
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/templates/entities_history_template.ts b/x-pack/plugins/observability_solution/entity_manager/server/templates/entities_history_template.ts
index d5ceeecd44828..63d589bfaa754 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/templates/entities_history_template.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/templates/entities_history_template.ts
@@ -6,29 +6,35 @@
*/
import { IndicesPutIndexTemplateRequest } from '@elastic/elasticsearch/lib/api/types';
+import { getEntityHistoryIndexTemplateV1 } from '../../common/helpers';
import {
ENTITY_ENTITY_COMPONENT_TEMPLATE_V1,
ENTITY_EVENT_COMPONENT_TEMPLATE_V1,
ENTITY_HISTORY_BASE_COMPONENT_TEMPLATE_V1,
ENTITY_HISTORY_INDEX_PREFIX_V1,
- ENTITY_HISTORY_INDEX_TEMPLATE_V1,
} from '../../common/constants_entities';
+import { getCustomHistoryTemplateComponents } from './components/helpers';
-export const entitiesHistoryIndexTemplateConfig: IndicesPutIndexTemplateRequest = {
- name: ENTITY_HISTORY_INDEX_TEMPLATE_V1,
+export const getEntitiesHistoryIndexTemplateConfig = (
+ definitionId: string
+): IndicesPutIndexTemplateRequest => ({
+ name: getEntityHistoryIndexTemplateV1(definitionId),
_meta: {
description:
"Index template for indices managed by the Elastic Entity Model's entity discovery framework for the history dataset",
ecs_version: '8.0.0',
managed: true,
+ managed_by: 'elastic_entity_model',
},
+ ignore_missing_component_templates: getCustomHistoryTemplateComponents(definitionId),
composed_of: [
ENTITY_HISTORY_BASE_COMPONENT_TEMPLATE_V1,
ENTITY_ENTITY_COMPONENT_TEMPLATE_V1,
ENTITY_EVENT_COMPONENT_TEMPLATE_V1,
+ ...getCustomHistoryTemplateComponents(definitionId),
],
index_patterns: [`${ENTITY_HISTORY_INDEX_PREFIX_V1}.*`],
- priority: 1,
+ priority: 200,
template: {
mappings: {
_meta: {
@@ -72,4 +78,4 @@ export const entitiesHistoryIndexTemplateConfig: IndicesPutIndexTemplateRequest
},
},
},
-};
+});
diff --git a/x-pack/plugins/observability_solution/entity_manager/server/templates/entities_latest_template.ts b/x-pack/plugins/observability_solution/entity_manager/server/templates/entities_latest_template.ts
index f601c3aa9d57d..3ad09e7257a1a 100644
--- a/x-pack/plugins/observability_solution/entity_manager/server/templates/entities_latest_template.ts
+++ b/x-pack/plugins/observability_solution/entity_manager/server/templates/entities_latest_template.ts
@@ -6,26 +6,32 @@
*/
import { IndicesPutIndexTemplateRequest } from '@elastic/elasticsearch/lib/api/types';
+import { getEntityLatestIndexTemplateV1 } from '../../common/helpers';
import {
ENTITY_ENTITY_COMPONENT_TEMPLATE_V1,
ENTITY_EVENT_COMPONENT_TEMPLATE_V1,
ENTITY_LATEST_BASE_COMPONENT_TEMPLATE_V1,
ENTITY_LATEST_INDEX_PREFIX_V1,
- ENTITY_LATEST_INDEX_TEMPLATE_V1,
} from '../../common/constants_entities';
+import { getCustomLatestTemplateComponents } from './components/helpers';
-export const entitiesLatestIndexTemplateConfig: IndicesPutIndexTemplateRequest = {
- name: ENTITY_LATEST_INDEX_TEMPLATE_V1,
+export const getEntitiesLatestIndexTemplateConfig = (
+ definitionId: string
+): IndicesPutIndexTemplateRequest => ({
+ name: getEntityLatestIndexTemplateV1(definitionId),
_meta: {
description:
"Index template for indices managed by the Elastic Entity Model's entity discovery framework for the latest dataset",
ecs_version: '8.0.0',
managed: true,
+ managed_by: 'elastic_entity_model',
},
+ ignore_missing_component_templates: getCustomLatestTemplateComponents(definitionId),
composed_of: [
ENTITY_LATEST_BASE_COMPONENT_TEMPLATE_V1,
ENTITY_ENTITY_COMPONENT_TEMPLATE_V1,
ENTITY_EVENT_COMPONENT_TEMPLATE_V1,
+ ...getCustomLatestTemplateComponents(definitionId),
],
index_patterns: [`${ENTITY_LATEST_INDEX_PREFIX_V1}.*`],
priority: 1,
@@ -72,4 +78,4 @@ export const entitiesLatestIndexTemplateConfig: IndicesPutIndexTemplateRequest =
},
},
},
-};
+});
diff --git a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/profiling/functions.tsx b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/profiling/functions.tsx
index 811172fca2695..5dee9438b280c 100644
--- a/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/profiling/functions.tsx
+++ b/x-pack/plugins/observability_solution/infra/public/components/asset_details/tabs/profiling/functions.tsx
@@ -31,11 +31,13 @@ export function Functions({ kuery }: Props) {
const { dateRange, getDateRangeInTimestamp } = useDatePickerContext();
const { from, to } = getDateRangeInTimestamp();
const { request$ } = useRequestObservable();
+ const { renderMode } = useAssetDetailsRenderPropsContext();
const profilingLinkLocator = services.observabilityShared.locators.profiling.topNFunctionsLocator;
const profilingLinkLabel = i18n.translate('xpack.infra.flamegraph.profilingAppTopFunctionsLink', {
defaultMessage: 'Go to Universal Profiling Functions',
});
+ const showFullScreenSelector = renderMode.mode === 'page';
const params = useMemo(
() => ({
@@ -86,6 +88,7 @@ export function Functions({ kuery }: Props) {
rangeFrom={from}
rangeTo={to}
height="60vh"
+ showFullScreenSelector={showFullScreenSelector}
/>
>
);
diff --git a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_functions.tsx b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_functions.tsx
index c4fad57b890ce..aa5d3c335ec05 100644
--- a/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_functions.tsx
+++ b/x-pack/plugins/observability_solution/observability_shared/public/components/profiling/embeddables/embeddable_functions.tsx
@@ -17,6 +17,7 @@ interface Props {
rangeFrom: number;
rangeTo: number;
height?: string;
+ showFullScreenSelector?: boolean;
}
export function EmbeddableFunctions(props: Props) {
diff --git a/x-pack/plugins/observability_solution/profiling/public/components/topn_functions/index.tsx b/x-pack/plugins/observability_solution/profiling/public/components/topn_functions/index.tsx
index 4f56865d54a84..cad716654a843 100644
--- a/x-pack/plugins/observability_solution/profiling/public/components/topn_functions/index.tsx
+++ b/x-pack/plugins/observability_solution/profiling/public/components/topn_functions/index.tsx
@@ -32,6 +32,7 @@ interface Props {
comparisonTopNFunctions?: TopNFunctions;
totalSeconds: number;
isDifferentialView: boolean;
+ showFullScreenSelector?: boolean;
baselineScaleFactor?: number;
comparisonScaleFactor?: number;
onFrameClick?: (functionName: string) => void;
@@ -50,6 +51,7 @@ export const TopNFunctionsGrid = ({
topNFunctions,
comparisonTopNFunctions,
totalSeconds,
+ showFullScreenSelector = true,
isDifferentialView,
baselineScaleFactor,
comparisonScaleFactor,
@@ -316,7 +318,7 @@ export const TopNFunctionsGrid = ({
showColumnSelector: false,
showKeyboardShortcuts: !isDifferentialView,
showDisplaySelector: !isDifferentialView,
- showFullScreenSelector: !isDifferentialView,
+ showFullScreenSelector: showFullScreenSelector && !isDifferentialView,
showSortSelector: false,
}}
virtualizationOptions={{
diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions.tsx
index e281f12224c8f..851eeeb8fe103 100644
--- a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions.tsx
+++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions.tsx
@@ -23,6 +23,7 @@ export interface FunctionsProps {
isLoading: boolean;
rangeFrom: number;
rangeTo: number;
+ showFullScreenSelector?: boolean;
}
export function EmbeddableFunctions({
@@ -30,6 +31,7 @@ export function EmbeddableFunctions({
isLoading,
rangeFrom,
rangeTo,
+ showFullScreenSelector,
...deps
}: EmbeddableFunctionsProps) {
const totalSeconds = useMemo(() => (rangeTo - rangeFrom) / 1000, [rangeFrom, rangeTo]);
@@ -37,7 +39,11 @@ export function EmbeddableFunctions({
-
+
diff --git a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions_grid.tsx b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions_grid.tsx
index 5579217a59d22..8b4dfd5d62c27 100644
--- a/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions_grid.tsx
+++ b/x-pack/plugins/observability_solution/profiling/public/embeddables/functions/embeddable_functions_grid.tsx
@@ -13,9 +13,10 @@ import { TopNFunctionsGrid } from '../../components/topn_functions';
interface Props {
data?: TopNFunctions;
totalSeconds: number;
+ showFullScreenSelector?: boolean;
}
-export function EmbeddableFunctionsGrid({ data, totalSeconds }: Props) {
+export function EmbeddableFunctionsGrid({ data, totalSeconds, showFullScreenSelector }: Props) {
const [sortField, setSortField] = useState(TopNFunctionSortField.Rank);
const [sortDirection, setSortDirection] = useState<'asc' | 'desc'>('asc');
const [pageIndex, setPageIndex] = useState(0);
@@ -34,6 +35,7 @@ export function EmbeddableFunctionsGrid({ data, totalSeconds }: Props) {
setSortDirection(sorting.direction);
}}
isEmbedded
+ showFullScreenSelector={showFullScreenSelector}
/>
);
}
diff --git a/x-pack/plugins/observability_solution/synthetics/kibana.jsonc b/x-pack/plugins/observability_solution/synthetics/kibana.jsonc
index 3e0715e48abb1..c527630b85d6c 100644
--- a/x-pack/plugins/observability_solution/synthetics/kibana.jsonc
+++ b/x-pack/plugins/observability_solution/synthetics/kibana.jsonc
@@ -17,6 +17,7 @@
"embeddable",
"discover",
"dataViews",
+ "dashboard",
"encryptedSavedObjects",
"exploratoryView",
"features",
@@ -31,7 +32,9 @@
"triggersActionsUi",
"usageCollection",
"bfetch",
- "unifiedSearch"
+ "uiActions",
+ "unifiedSearch",
+ "presentationUtil"
],
"optionalPlugins": [
"cloud",
@@ -53,7 +56,7 @@
"observability",
"spaces",
"indexLifecycleManagement",
- "unifiedDocViewer"
+ "unifiedDocViewer",
]
}
}
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/constants.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/constants.ts
new file mode 100644
index 0000000000000..b471d46ac3832
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/constants.ts
@@ -0,0 +1,8 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+export const SYNTHETICS_OVERVIEW_EMBEDDABLE = 'SYNTHETICS_OVERVIEW_EMBEDDABLE';
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/register_embeddables.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/register_embeddables.ts
new file mode 100644
index 0000000000000..fbc516a6f611b
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/register_embeddables.ts
@@ -0,0 +1,48 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { CoreSetup } from '@kbn/core-lifecycle-browser';
+
+import { ADD_PANEL_TRIGGER } from '@kbn/ui-actions-browser/src';
+import { createStatusOverviewPanelAction } from './ui_actions/create_overview_panel_action';
+import { ClientPluginsSetup, ClientPluginsStart } from '../../plugin';
+import { SYNTHETICS_OVERVIEW_EMBEDDABLE } from './constants';
+
+export const registerSyntheticsEmbeddables = (
+ core: CoreSetup,
+ pluginsSetup: ClientPluginsSetup
+) => {
+ pluginsSetup.embeddable.registerReactEmbeddableFactory(
+ SYNTHETICS_OVERVIEW_EMBEDDABLE,
+ async () => {
+ const { getStatusOverviewEmbeddableFactory } = await import(
+ './status_overview/status_overview_embeddable_factory'
+ );
+ return getStatusOverviewEmbeddableFactory(core.getStartServices);
+ }
+ );
+
+ const { uiActions, cloud, serverless } = pluginsSetup;
+
+ // Initialize actions
+ const addOverviewPanelAction = createStatusOverviewPanelAction();
+
+ core.getStartServices().then(([_, pluginsStart]) => {
+ pluginsStart.dashboard.registerDashboardPanelPlacementSetting(
+ SYNTHETICS_OVERVIEW_EMBEDDABLE,
+ () => {
+ return { width: 10, height: 8 };
+ }
+ );
+ });
+
+ // Assign triggers
+ // Only register these actions in stateful kibana, and the serverless observability project
+ if (Boolean((serverless && cloud?.serverless.projectType === 'observability') || !serverless)) {
+ uiActions.addTriggerAction(ADD_PANEL_TRIGGER, addOverviewPanelAction);
+ }
+};
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/status_overview/status_overview_component.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/status_overview/status_overview_component.tsx
new file mode 100644
index 0000000000000..1034f9ea959ec
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/status_overview/status_overview_component.tsx
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { Subject } from 'rxjs';
+import { OverviewStatus } from '../../synthetics/components/monitors_page/overview/overview/overview_status';
+import { SyntheticsEmbeddableContext } from '../synthetics_embeddable_context';
+
+export const StatusOverviewComponent = ({ reload$ }: { reload$: Subject }) => {
+ return (
+
+
+
+ );
+};
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/status_overview/status_overview_embeddable_factory.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/status_overview/status_overview_embeddable_factory.tsx
new file mode 100644
index 0000000000000..3f7b3fcf13699
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/status_overview/status_overview_embeddable_factory.tsx
@@ -0,0 +1,99 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { i18n } from '@kbn/i18n';
+
+import React, { useEffect } from 'react';
+import { DefaultEmbeddableApi, ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public';
+import {
+ initializeTitles,
+ useBatchedPublishingSubjects,
+ fetch$,
+ PublishesWritablePanelTitle,
+ PublishesPanelTitle,
+ SerializedTitles,
+} from '@kbn/presentation-publishing';
+import { BehaviorSubject, Subject } from 'rxjs';
+import type { StartServicesAccessor } from '@kbn/core-lifecycle-browser';
+import { SYNTHETICS_OVERVIEW_EMBEDDABLE } from '../constants';
+import { ClientPluginsStart } from '../../../plugin';
+import { StatusOverviewComponent } from './status_overview_component';
+
+export const getOverviewPanelTitle = () =>
+ i18n.translate('xpack.synthetics.statusOverview.displayName', {
+ defaultMessage: 'Synthetics Status Overview',
+ });
+
+export type OverviewEmbeddableState = SerializedTitles;
+
+export type StatusOverviewApi = DefaultEmbeddableApi &
+ PublishesWritablePanelTitle &
+ PublishesPanelTitle;
+
+export const getStatusOverviewEmbeddableFactory = (
+ getStartServices: StartServicesAccessor
+) => {
+ const factory: ReactEmbeddableFactory<
+ OverviewEmbeddableState,
+ OverviewEmbeddableState,
+ StatusOverviewApi
+ > = {
+ type: SYNTHETICS_OVERVIEW_EMBEDDABLE,
+ deserializeState: (state) => {
+ return state.rawState as OverviewEmbeddableState;
+ },
+ buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
+ const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state);
+ const defaultTitle$ = new BehaviorSubject(getOverviewPanelTitle());
+ const reload$ = new Subject();
+
+ const api = buildApi(
+ {
+ ...titlesApi,
+ defaultPanelTitle: defaultTitle$,
+ serializeState: () => {
+ return {
+ rawState: {
+ ...serializeTitles(),
+ },
+ };
+ },
+ },
+ {
+ ...titleComparators,
+ }
+ );
+
+ const fetchSubscription = fetch$(api)
+ .pipe()
+ .subscribe((next) => {
+ reload$.next(next.isReload);
+ });
+
+ return {
+ api,
+ Component: () => {
+ const [] = useBatchedPublishingSubjects();
+
+ useEffect(() => {
+ return () => {
+ fetchSubscription.unsubscribe();
+ };
+ }, []);
+ return (
+
+
+
+ );
+ },
+ };
+ },
+ };
+ return factory;
+};
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/synthetics_embeddable_context.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/synthetics_embeddable_context.tsx
new file mode 100644
index 0000000000000..0953fb79961b1
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/synthetics_embeddable_context.tsx
@@ -0,0 +1,34 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { createBrowserHistory } from 'history';
+import { EuiPanel } from '@elastic/eui';
+import { Router } from '@kbn/shared-ux-router';
+import { SyntheticsSharedContext } from '../synthetics/contexts/synthetics_shared_context';
+import { SyntheticsEmbeddableStateContextProvider } from '../synthetics/contexts/synthetics_embeddable_context';
+import { getSyntheticsAppProps } from '../synthetics/render_app';
+import { SyntheticsSettingsContextProvider } from '../synthetics/contexts';
+
+export const SyntheticsEmbeddableContext: React.FC<{ search?: string }> = ({
+ search,
+ children,
+}) => {
+ const props = getSyntheticsAppProps();
+
+ return (
+
+
+
+
+ {children}
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/ui_actions/create_overview_panel_action.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/ui_actions/create_overview_panel_action.tsx
new file mode 100644
index 0000000000000..202a09e1f3576
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/ui_actions/create_overview_panel_action.tsx
@@ -0,0 +1,54 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import { i18n } from '@kbn/i18n';
+import { apiIsPresentationContainer } from '@kbn/presentation-containers';
+import {
+ IncompatibleActionError,
+ type UiActionsActionDefinition,
+} from '@kbn/ui-actions-plugin/public';
+import { EmbeddableApiContext } from '@kbn/presentation-publishing';
+import { SYNTHETICS_OVERVIEW_EMBEDDABLE } from '../constants';
+
+export const COMMON_SYNTHETICS_GROUPING = [
+ {
+ id: 'synthetics',
+ getDisplayName: () =>
+ i18n.translate('xpack.synthetics.common.constants.grouping.legacy', {
+ defaultMessage: 'Synthetics',
+ }),
+ getIconType: () => {
+ return 'online';
+ },
+ },
+];
+export const ADD_SYNTHETICS_OVERVIEW_ACTION_ID = 'CREATE_SYNTHETICS_OVERVIEW_EMBEDDABLE';
+
+export function createStatusOverviewPanelAction(): UiActionsActionDefinition {
+ return {
+ id: ADD_SYNTHETICS_OVERVIEW_ACTION_ID,
+ grouping: COMMON_SYNTHETICS_GROUPING,
+ order: 30,
+ getIconType: () => 'online',
+ isCompatible: async ({ embeddable }) => {
+ return apiIsPresentationContainer(embeddable);
+ },
+ execute: async ({ embeddable }) => {
+ if (!apiIsPresentationContainer(embeddable)) throw new IncompatibleActionError();
+ try {
+ embeddable.addNewPanel({
+ panelType: SYNTHETICS_OVERVIEW_EMBEDDABLE,
+ });
+ } catch (e) {
+ return Promise.reject();
+ }
+ },
+ getDisplayName: () =>
+ i18n.translate('xpack.synthetics.syntheticsEmbeddable.ariaLabel', {
+ defaultMessage: 'Synthetics Overview',
+ }),
+ };
+}
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/alerting_callout/alerting_callout.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/alerting_callout/alerting_callout.tsx
index 07c594aa56156..4b508ab701231 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/alerting_callout/alerting_callout.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/alerting_callout/alerting_callout.tsx
@@ -14,6 +14,8 @@ import { useFetcher } from '@kbn/observability-shared-plugin/public';
import { useSessionStorage } from 'react-use';
import { i18n } from '@kbn/i18n';
import { isEmpty } from 'lodash';
+import { useKibana } from '@kbn/kibana-react-plugin/public';
+import { ClientPluginsStart } from '../../../../../plugin';
import { selectDynamicSettings } from '../../../state/settings';
import {
selectSyntheticsAlerts,
@@ -21,7 +23,7 @@ import {
} from '../../../state/alert_rules/selectors';
import { selectMonitorListState } from '../../../state';
import { getDynamicSettingsAction } from '../../../state/settings/actions';
-import { useSyntheticsSettingsContext, useSyntheticsStartPlugins } from '../../../contexts';
+import { useSyntheticsSettingsContext } from '../../../contexts';
import { ConfigKey } from '../../../../../../common/runtime_types';
export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boolean }) => {
@@ -40,7 +42,8 @@ export const AlertingCallout = ({ isAlertingEnabled }: { isAlertingEnabled?: boo
loaded: monitorsLoaded,
} = useSelector(selectMonitorListState);
- const syntheticsLocators = useSyntheticsStartPlugins()?.share?.url.locators;
+ const syntheticsLocators = useKibana().services.share?.url.locators;
+
const locator = syntheticsLocators?.get(syntheticsSettingsLocatorID);
const { data: url } = useFetcher(() => {
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/components/embeddable_panel_wrapper.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/components/embeddable_panel_wrapper.tsx
new file mode 100644
index 0000000000000..cd73097c956a6
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/components/embeddable_panel_wrapper.tsx
@@ -0,0 +1,139 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { FC, useCallback } from 'react';
+import { i18n } from '@kbn/i18n';
+import {
+ EuiButtonIcon,
+ EuiContextMenuItem,
+ EuiContextMenuPanel,
+ EuiFlexGroup,
+ EuiFlexItem,
+ EuiPanel,
+ EuiPopover,
+ EuiProgress,
+ EuiTitle,
+} from '@elastic/eui';
+import {
+ LazySavedObjectSaveModalDashboard,
+ SaveModalDashboardProps,
+ withSuspense,
+} from '@kbn/presentation-util-plugin/public';
+import { useKibana } from '@kbn/kibana-react-plugin/public';
+import { SYNTHETICS_OVERVIEW_EMBEDDABLE } from '../../../../embeddables/constants';
+import { ClientPluginsStart } from '../../../../../plugin';
+
+const SavedObjectSaveModalDashboard = withSuspense(LazySavedObjectSaveModalDashboard);
+
+export const EmbeddablePanelWrapper: FC<{
+ title: string;
+ loading?: boolean;
+}> = ({ children, title, loading }) => {
+ const [isPopoverOpen, setIsPopoverOpen] = React.useState(false);
+
+ const [isDashboardAttachmentReady, setDashboardAttachmentReady] = React.useState(false);
+
+ const closePopover = () => {
+ setIsPopoverOpen(false);
+ };
+
+ const { embeddable } = useKibana().services;
+
+ const isSyntheticsApp = window.location.pathname.includes('/app/synthetics');
+
+ const handleAttachToDashboardSave: SaveModalDashboardProps['onSave'] = useCallback(
+ ({ dashboardId, newTitle, newDescription }) => {
+ const stateTransfer = embeddable.getStateTransfer();
+ const embeddableInput = {};
+
+ const state = {
+ input: embeddableInput,
+ type: SYNTHETICS_OVERVIEW_EMBEDDABLE,
+ };
+
+ const path = dashboardId === 'new' ? '#/create' : `#/view/${dashboardId}`;
+
+ stateTransfer.navigateToWithEmbeddablePackage('dashboards', {
+ state,
+ path,
+ });
+ },
+ [embeddable]
+ );
+
+ return (
+ <>
+
+ {loading && }
+
+
+
+ {title}
+
+
+ {isSyntheticsApp && (
+
+ setIsPopoverOpen(!isPopoverOpen)}
+ />
+ }
+ isOpen={isPopoverOpen}
+ closePopover={closePopover}
+ >
+ {
+ setDashboardAttachmentReady(true);
+ closePopover();
+ }}
+ >
+ {i18n.translate(
+ 'xpack.synthetics.embeddablePanelWrapper.shareContextMenuItemLabel',
+ { defaultMessage: 'Add to dashboard' }
+ )}
+ ,
+ ]}
+ />
+
+
+ )}
+
+
+ {children}
+
+ {isDashboardAttachmentReady ? (
+ {
+ setDashboardAttachmentReady(false);
+ }}
+ onSave={handleAttachToDashboardSave}
+ />
+ ) : null}
+ >
+ );
+};
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.tsx
index a5eaeacf6c7ed..1edaf76ea95a8 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/date_picker/synthetics_date_picker.tsx
@@ -7,20 +7,18 @@
import React, { useContext, useEffect } from 'react';
import { EuiSuperDatePicker } from '@elastic/eui';
+import { useKibana } from '@kbn/kibana-react-plugin/public';
+import { ClientPluginsStart } from '../../../../../plugin';
import { useUrlParams } from '../../../hooks';
import { CLIENT_DEFAULTS } from '../../../../../../common/constants';
-import {
- SyntheticsSettingsContext,
- SyntheticsStartupPluginsContext,
- SyntheticsRefreshContext,
-} from '../../../contexts';
+import { SyntheticsSettingsContext, SyntheticsRefreshContext } from '../../../contexts';
export const SyntheticsDatePicker = ({ fullWidth }: { fullWidth?: boolean }) => {
const [getUrlParams, updateUrl] = useUrlParams();
const { commonlyUsedRanges } = useContext(SyntheticsSettingsContext);
const { refreshApp } = useContext(SyntheticsRefreshContext);
- const { data } = useContext(SyntheticsStartupPluginsContext);
+ const { data } = useKibana().services;
// read time from state and update the url
const sharedTimeState = data?.query.timefilter.timefilter.getTime();
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/step_field_trend/step_field_trend.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/step_field_trend/step_field_trend.tsx
index 7b687929b78a5..47794a31b8e1c 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/step_field_trend/step_field_trend.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/step_field_trend/step_field_trend.tsx
@@ -12,9 +12,9 @@ import moment from 'moment';
import { AllSeries, createExploratoryViewUrl } from '@kbn/exploratory-view-plugin/public';
import { euiStyled } from '@kbn/kibana-react-plugin/common';
import { useKibana } from '@kbn/kibana-react-plugin/public';
+import { ClientPluginsStart } from '../../../../../plugin';
import { SYNTHETICS_INDEX_PATTERN } from '../../../../../../common/constants';
import { JourneyStep } from '../../../../../../common/runtime_types';
-import { useSyntheticsStartPlugins } from '../../../contexts';
export const getLast48Intervals = (activeStep: JourneyStep) => {
const timestamp = activeStep['@timestamp'];
@@ -36,7 +36,7 @@ export function StepFieldTrend({
field: string;
step: JourneyStep;
}) {
- const { exploratoryView } = useSyntheticsStartPlugins();
+ const exploratoryView = useKibana().services.exploratoryView;
const EmbeddableExpView = exploratoryView!.ExploratoryViewEmbeddable;
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.test.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.test.tsx
index 9c51fdf6b7b6e..2587fe21fba21 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.test.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/getting_started/getting_started_page.test.tsx
@@ -179,7 +179,7 @@ describe('GettingStartedPage', () => {
});
// page is loaded
- expect(kibanaService.core.application.navigateToApp).toHaveBeenCalledWith('synthetics', {
+ expect(kibanaService.coreStart.application.navigateToApp).toHaveBeenCalledWith('synthetics', {
path: '/monitors',
});
});
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/getting_started/use_simple_monitor.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/getting_started/use_simple_monitor.ts
index e4015386ff333..250b6442ce1d1 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/getting_started/use_simple_monitor.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/getting_started/use_simple_monitor.ts
@@ -56,14 +56,14 @@ export const useSimpleMonitor = ({ monitorData }: { monitorData?: SimpleFormData
}, [monitorData]);
useEffect(() => {
- const { core, toasts } = kibanaService;
+ const { coreStart, toasts } = kibanaService;
const newMonitor = data as UpsertMonitorResponse;
const hasErrors = data && 'attributes' in data && data.attributes.errors?.length > 0;
if (hasErrors && !loading) {
showSyncErrors(
(data as { attributes: { errors: ServiceLocationErrors } })?.attributes.errors ?? [],
serviceLocations,
- core
+ coreStart
);
}
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/hooks/use_monitor_save.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/hooks/use_monitor_save.tsx
index 1ba3cec885889..44def6edee978 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/hooks/use_monitor_save.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/hooks/use_monitor_save.tsx
@@ -45,7 +45,7 @@ export const useMonitorSave = ({ monitorData }: { monitorData?: SyntheticsMonito
}, [monitorData]);
useEffect(() => {
- const { core, toasts } = kibanaService;
+ const { coreStart, toasts } = kibanaService;
if (status === FETCH_STATUS.FAILURE && error) {
toasts.addError(
@@ -64,7 +64,7 @@ export const useMonitorSave = ({ monitorData }: { monitorData?: SyntheticsMonito
{monitorId ? MONITOR_UPDATED_SUCCESS_LABEL_SUBTEXT : MONITOR_SUCCESS_LABEL_SUBTEXT}
,
- core
+ coreStart
),
toastLifeTimeMs: 3000,
});
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_overview_status.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_overview_status.ts
index b06b66f8a5a73..562d651cf819b 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_overview_status.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/hooks/use_overview_status.ts
@@ -18,7 +18,7 @@ import {
export function useOverviewStatus({ scopeStatusByLocation }: { scopeStatusByLocation: boolean }) {
const pageState = useSelector(selectOverviewPageState);
- const { status, error, loaded } = useSelector(selectOverviewStatus);
+ const { status, error, loaded, loading } = useSelector(selectOverviewStatus);
const { lastRefresh } = useSyntheticsRefreshContext();
@@ -37,5 +37,6 @@ export function useOverviewStatus({ scopeStatusByLocation }: { scopeStatusByLoca
return {
status,
error,
+ loading,
};
}
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/delete_monitor.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/delete_monitor.tsx
index b16829fa5880a..dab31650aec4d 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/delete_monitor.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/management/monitor_list_table/delete_monitor.tsx
@@ -42,7 +42,7 @@ export const DeleteMonitor = ({
}, [configId, isDeleting]);
useEffect(() => {
- const { core, toasts } = kibanaService;
+ const { coreStart, toasts } = kibanaService;
if (!isDeleting) {
return;
}
@@ -53,7 +53,7 @@ export const DeleteMonitor = ({
{labels.MONITOR_DELETE_FAILURE_LABEL}
,
- core
+ coreStart
),
},
{ toastLifeTimeMs: 3000 }
@@ -72,7 +72,7 @@ export const DeleteMonitor = ({
}
)}
,
- core
+ coreStart
),
},
{ toastLifeTimeMs: 3000 }
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx
index 53f14deb0dab5..49f21acc20f10 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_grid.tsx
@@ -4,7 +4,7 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
-import React, { useState, useRef, memo, useCallback } from 'react';
+import React, { useState, useRef, memo, useCallback, useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { i18n } from '@kbn/i18n';
import {
@@ -15,11 +15,12 @@ import {
EuiButtonEmpty,
EuiText,
} from '@elastic/eui';
-import { selectOverviewStatus } from '../../../../state/overview_status';
+import { useOverviewStatus } from '../../hooks/use_overview_status';
import { useInfiniteScroll } from './use_infinite_scroll';
import { GridItemsByGroup } from './grid_by_group/grid_items_by_group';
import { GroupFields } from './grid_by_group/group_fields';
import {
+ fetchMonitorOverviewAction,
quietFetchOverviewAction,
selectOverviewState,
setFlyoutConfig,
@@ -33,7 +34,7 @@ import { NoMonitorsFound } from '../../common/no_monitors_found';
import { MonitorDetailFlyout } from './monitor_detail_flyout';
export const OverviewGrid = memo(() => {
- const { status } = useSelector(selectOverviewStatus);
+ const { status } = useOverviewStatus({ scopeStatusByLocation: true });
const {
data: { monitors },
@@ -49,6 +50,11 @@ export const OverviewGrid = memo(() => {
const intersectionRef = useRef(null);
const { monitorsSortedByStatus } = useMonitorsSortedByStatus();
+ // fetch overview for all other page state changes
+ useEffect(() => {
+ dispatch(fetchMonitorOverviewAction.get(pageState));
+ }, [dispatch, pageState]);
+
const setFlyoutConfigCallback = useCallback(
(params: FlyoutParamProps) => dispatch(setFlyoutConfig(params)),
[dispatch]
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx
index fd3e19c7e96f0..28eaf97a37c5f 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitors_page/overview/overview/overview_status.tsx
@@ -5,10 +5,13 @@
* 2.0.
*/
-import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiSpacer, EuiStat, EuiTitle } from '@elastic/eui';
+import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiStat } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import React, { useEffect, useState } from 'react';
import { useDispatch } from 'react-redux';
+import { Subject } from 'rxjs';
+import { useSyntheticsRefreshContext } from '../../../../contexts';
+import { EmbeddablePanelWrapper } from '../../../common/components/embeddable_panel_wrapper';
import { clearOverviewStatusErrorAction } from '../../../../state/overview_status';
import { kibanaService } from '../../../../../../utils/kibana_service';
import { useGetUrlParams } from '../../../../hooks/use_url_params';
@@ -18,10 +21,16 @@ function title(t?: number) {
return t ?? '-';
}
-export function OverviewStatus() {
+export function OverviewStatus({ reload$ }: { reload$?: Subject }) {
const { statusFilter } = useGetUrlParams();
- const { status, error: statusError } = useOverviewStatus({ scopeStatusByLocation: true });
+ const { refreshApp } = useSyntheticsRefreshContext();
+
+ const {
+ status,
+ error: statusError,
+ loading,
+ } = useOverviewStatus({ scopeStatusByLocation: true });
const dispatch = useDispatch();
const [statusConfig, setStatusConfig] = useState({
up: status?.up,
@@ -30,6 +39,14 @@ export function OverviewStatus() {
disabledCount: status?.disabledCount,
});
+ useEffect(() => {
+ const sub = reload$?.subscribe(() => {
+ refreshApp();
+ });
+
+ return () => sub?.unsubscribe();
+ }, [refreshApp, reload$]);
+
useEffect(() => {
if (statusError) {
dispatch(clearOverviewStatusErrorAction());
@@ -87,10 +104,7 @@ export function OverviewStatus() {
}, [status, statusFilter]);
return (
-
-
- {headingText}
-
+
@@ -136,7 +150,7 @@ export function OverviewStatus() {
)}
-
+
);
}
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/delete_param.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/delete_param.tsx
index f2e86f077123d..814fb13a99ba9 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/delete_param.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/settings/global_params/delete_param.tsx
@@ -48,7 +48,7 @@ export const DeleteParam = ({
if (!isDeleting) {
return;
}
- const { core, toasts } = kibanaService;
+ const { coreStart, toasts } = kibanaService;
if (status === FETCH_STATUS.FAILURE) {
toasts.addDanger(
@@ -61,7 +61,7 @@ export const DeleteParam = ({
values: { name },
})}
,
- core
+ coreStart
),
},
{ toastLifeTimeMs: 3000 }
@@ -76,7 +76,7 @@ export const DeleteParam = ({
values: { name },
})}
,
- core
+ coreStart
),
},
{ toastLifeTimeMs: 3000 }
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_test_helper.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_test_helper.tsx
index b30cd29a0f065..93afcb3c55bbb 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_test_helper.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/step_details_page/step_waterfall_chart/waterfall/waterfall_marker/waterfall_marker_test_helper.tsx
@@ -5,8 +5,9 @@
* 2.0.
*/
+import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import React from 'react';
-import { SyntheticsStartupPluginsContext } from '../../../../../contexts';
+import { i18n } from '@kbn/i18n';
import { JourneyStep } from '../../../../../../../../common/runtime_types';
import { WaterfallContext } from '../context/waterfall_context';
@@ -25,9 +26,21 @@ const EmbeddableMock = ({
}) => (
{title}
-
{appendTitle}
+
+ {appendTitle}
+
{reportType}
-
{JSON.stringify(attributes)}
+
+ {JSON.stringify(attributes)}
+
);
@@ -40,9 +53,8 @@ export const TestWrapper = ({
activeStep?: JourneyStep;
children: JSX.Element;
}) => (
- ),
},
@@ -55,5 +67,5 @@ export const TestWrapper = ({
>
{children}
-
+
);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/browser_test_results.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/browser_test_results.tsx
index 326e981d2c4e2..7aaeb39bf46e6 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/browser_test_results.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/browser_test_results.tsx
@@ -38,7 +38,7 @@ export const BrowserTestRunResult = ({
});
useEffect(() => {
- const { core, toasts } = kibanaService;
+ const { coreStart, toasts } = kibanaService;
if (retriesExceeded) {
toasts.addDanger(
{
@@ -49,7 +49,7 @@ export const BrowserTestRunResult = ({
defaultMessage="Manual test run failed for {name}"
values={{ name }}
/>,
- core
+ coreStart
),
},
{
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/simple_test_results.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/simple_test_results.tsx
index f88b6b3483a43..ba9d4ff87566c 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/simple_test_results.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/test_now_mode/manual_test_run_mode/simple_test_results.tsx
@@ -25,7 +25,7 @@ export function SimpleTestResults({ name, testRunId, expectPings, onDone }: Prop
useEffect(() => {
if (retriesExceeded) {
- const { core, toasts } = kibanaService;
+ const { coreStart, toasts } = kibanaService;
toasts.addDanger(
{
@@ -36,7 +36,7 @@ export function SimpleTestResults({ name, testRunId, expectPings, onDone }: Prop
defaultMessage="Manual test run failed for {name}"
values={{ name }}
/>,
- core
+ coreStart
),
},
{
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/index.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/index.ts
index e3171165a8639..662d6337d5a0e 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/index.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/index.ts
@@ -7,5 +7,3 @@
export * from './synthetics_refresh_context';
export * from './synthetics_settings_context';
-export * from './synthetics_theme_context';
-export * from './synthetics_startup_plugins_context';
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_embeddable_context.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_embeddable_context.tsx
new file mode 100644
index 0000000000000..0ae588714bf97
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_embeddable_context.tsx
@@ -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
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React, { createContext, useContext, useMemo } from 'react';
+import { History, createMemoryHistory } from 'history';
+
+interface SyntheticsEmbeddableContext {
+ history: History;
+}
+
+const defaultContext: SyntheticsEmbeddableContext = {} as SyntheticsEmbeddableContext;
+
+export const SyntheticsEmbeddableContext = createContext(defaultContext);
+
+export const SyntheticsEmbeddableStateContextProvider: React.FC = ({ children }) => {
+ const value = useMemo(() => {
+ return { history: createMemoryHistory() };
+ }, []);
+
+ return ;
+};
+
+export const useSyntheticsEmbeddableContext = () => useContext(SyntheticsEmbeddableContext);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx
index b221997efe9c3..14799683d96d5 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_settings_context.tsx
@@ -27,13 +27,13 @@ export interface CommonlyUsedDateRange {
export interface SyntheticsAppProps {
basePath: string;
canSave: boolean;
- core: CoreStart;
+ coreStart: CoreStart;
darkMode: boolean;
i18n: I18nStart;
isApmAvailable: boolean;
isInfraAvailable: boolean;
isLogsAvailable: boolean;
- plugins: ClientPluginsSetup;
+ setupPlugins: ClientPluginsSetup;
startPlugins: ClientPluginsStart;
setBadge: (badge?: ChromeBadge) => void;
renderGlobalHelpControls(): void;
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_shared_context.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_shared_context.tsx
new file mode 100644
index 0000000000000..948bf538c2faf
--- /dev/null
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_shared_context.tsx
@@ -0,0 +1,63 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import React from 'react';
+import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
+import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
+import { Provider as ReduxProvider } from 'react-redux';
+import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
+import { SyntheticsRefreshContextProvider } from './synthetics_refresh_context';
+import { SyntheticsDataViewContextProvider } from './synthetics_data_view_context';
+import { SyntheticsAppProps } from './synthetics_settings_context';
+import { storage, store } from '../state';
+
+export const SyntheticsSharedContext: React.FC = ({
+ coreStart,
+ setupPlugins,
+ startPlugins,
+ children,
+ darkMode,
+}) => {
+ return (
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+ );
+};
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_startup_plugins_context.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_startup_plugins_context.tsx
deleted file mode 100644
index cfb28cbbff553..0000000000000
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_startup_plugins_context.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import React, { createContext, useContext, PropsWithChildren } from 'react';
-import { ClientPluginsStart } from '../../../plugin';
-
-export const SyntheticsStartupPluginsContext = createContext>({});
-
-export const SyntheticsStartupPluginsContextProvider: React.FC<
- PropsWithChildren>
-> = ({ children, ...props }) => (
-
-);
-
-export const useSyntheticsStartPlugins = () => useContext(SyntheticsStartupPluginsContext);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_theme_context.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_theme_context.tsx
deleted file mode 100644
index b57bdaa0cd365..0000000000000
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/contexts/synthetics_theme_context.tsx
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { euiLightVars, euiDarkVars } from '@kbn/ui-theme';
-import React, { createContext, useContext, useMemo, FC, PropsWithChildren } from 'react';
-import { DARK_THEME, LIGHT_THEME, PartialTheme, Theme } from '@elastic/charts';
-
-export interface SyntheticsAppColors {
- danger: string;
- dangerBehindText: string;
- success: string;
- gray: string;
- range: string;
- mean: string;
- warning: string;
- lightestShade: string;
-}
-
-export interface SyntheticsThemeContextValues {
- colors: SyntheticsAppColors;
- chartTheme: {
- baseTheme?: Theme;
- theme?: PartialTheme;
- };
-}
-
-/**
- * These are default values for the context. These defaults are typically
- * overwritten by the Synthetics App upon its invocation.
- */
-const defaultContext: SyntheticsThemeContextValues = {
- colors: {
- danger: euiLightVars.euiColorDanger,
- dangerBehindText: euiDarkVars.euiColorVis9_behindText,
- mean: euiLightVars.euiColorPrimary,
- range: euiLightVars.euiFocusBackgroundColor,
- success: euiLightVars.euiColorSuccess,
- warning: euiLightVars.euiColorWarning,
- gray: euiLightVars.euiColorLightShade,
- lightestShade: euiLightVars.euiColorLightestShade,
- },
- chartTheme: {
- baseTheme: LIGHT_THEME,
- },
-};
-
-export const SyntheticsThemeContext = createContext(defaultContext);
-
-interface ThemeContextProps {
- darkMode: boolean;
-}
-
-export const SyntheticsThemeContextProvider: FC> = ({
- darkMode,
- children,
-}) => {
- let colors: SyntheticsAppColors;
- if (darkMode) {
- colors = {
- danger: euiDarkVars.euiColorVis9,
- dangerBehindText: euiDarkVars.euiColorVis9_behindText,
- mean: euiDarkVars.euiColorPrimary,
- gray: euiDarkVars.euiColorLightShade,
- range: euiDarkVars.euiFocusBackgroundColor,
- success: euiDarkVars.euiColorSuccess,
- warning: euiDarkVars.euiColorWarning,
- lightestShade: euiDarkVars.euiColorLightestShade,
- };
- } else {
- colors = {
- danger: euiLightVars.euiColorVis9,
- dangerBehindText: euiLightVars.euiColorVis9_behindText,
- mean: euiLightVars.euiColorPrimary,
- gray: euiLightVars.euiColorLightShade,
- range: euiLightVars.euiFocusBackgroundColor,
- success: euiLightVars.euiColorSuccess,
- warning: euiLightVars.euiColorWarning,
- lightestShade: euiLightVars.euiColorLightestShade,
- };
- }
- const value = useMemo(() => {
- return {
- colors,
- chartTheme: {
- baseTheme: darkMode ? DARK_THEME : LIGHT_THEME,
- },
- };
- }, [colors, darkMode]);
-
- return ;
-};
-
-export const useSyntheticsThemeContext = () => useContext(SyntheticsThemeContext);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_edit_monitor_locator.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_edit_monitor_locator.ts
index 034ca4ec6807a..a0ecb681e38c2 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_edit_monitor_locator.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_edit_monitor_locator.ts
@@ -8,7 +8,8 @@
import { useEffect, useState } from 'react';
import { LocatorClient } from '@kbn/share-plugin/common/url_service/locators';
import { syntheticsEditMonitorLocatorID } from '@kbn/observability-plugin/common';
-import { useSyntheticsStartPlugins } from '../contexts';
+import { useKibana } from '@kbn/kibana-react-plugin/public';
+import { ClientPluginsStart } from '../../../plugin';
export function useEditMonitorLocator({
configId,
@@ -18,7 +19,7 @@ export function useEditMonitorLocator({
locators?: LocatorClient;
}) {
const [editUrl, setEditUrl] = useState(undefined);
- const syntheticsLocators = useSyntheticsStartPlugins()?.share?.url.locators;
+ const syntheticsLocators = useKibana().services.share?.url.locators;
const locator = (locators || syntheticsLocators)?.get(syntheticsEditMonitorLocatorID);
useEffect(() => {
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_detail_locator.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_detail_locator.ts
index d1c181da28f17..fc346bccfa6c6 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_detail_locator.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/hooks/use_monitor_detail_locator.ts
@@ -7,7 +7,8 @@
import { useEffect, useState } from 'react';
import { syntheticsMonitorDetailLocatorID } from '@kbn/observability-plugin/common';
-import { useSyntheticsStartPlugins } from '../contexts';
+import { useKibana } from '@kbn/kibana-react-plugin/public';
+import { ClientPluginsStart } from '../../../plugin';
export function useMonitorDetailLocator({
configId,
@@ -17,7 +18,7 @@ export function useMonitorDetailLocator({
locationId?: string;
}) {
const [monitorUrl, setMonitorUrl] = useState(undefined);
- const locator = useSyntheticsStartPlugins()?.share?.url.locators.get(
+ const locator = useKibana().services?.share?.url.locators.get(
syntheticsMonitorDetailLocatorID
);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/lazy_wrapper/monitor_status.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/lazy_wrapper/monitor_status.tsx
index 7c33dc7aba96e..e0c843eca0bd4 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/lazy_wrapper/monitor_status.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/lazy_wrapper/monitor_status.tsx
@@ -19,19 +19,19 @@ import { store } from '../../../state';
import type { StatusRuleParams } from '../../../../../../common/rules/status_rule';
interface Props {
- core: CoreStart;
+ coreStart: CoreStart;
plugins: ClientPluginsStart;
params: RuleTypeParamsExpressionProps;
}
// eslint-disable-next-line import/no-default-export
-export default function MonitorStatusAlert({ core, plugins, params }: Props) {
- kibanaService.core = core;
+export default function MonitorStatusAlert({ coreStart, plugins, params }: Props) {
+ kibanaService.coreStart = coreStart;
const queryClient = new QueryClient();
return (
-
+
['ruleParams'];
setRuleParams: RuleTypeParamsExpressionProps['setRuleParams'];
}
// eslint-disable-next-line import/no-default-export
-export default function TLSAlert({ core, plugins, ruleParams, setRuleParams }: Props) {
- kibanaService.core = core;
+export default function TLSAlert({ coreStart, plugins, ruleParams, setRuleParams }: Props) {
+ kibanaService.coreStart = coreStart;
return (
-
+
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/monitor_status.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/monitor_status.tsx
index 8ee01e185e8c1..ba86407859408 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/monitor_status.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/monitor_status.tsx
@@ -33,7 +33,7 @@ export const initMonitorStatusAlertType: AlertTypeInitializer = ({
return `${docLinks.links.observability.syntheticsAlerting}`;
},
ruleParamsExpression: (paramProps: RuleTypeParamsExpressionProps) => (
-
+
),
validate: (_ruleParams: StatusRuleParams) => {
return { errors: {} };
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/tls.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/tls.tsx
index 2479d1f466f3e..15c0fa90ec605 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/tls.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/lib/alert_types/tls.tsx
@@ -31,7 +31,7 @@ export const initTlsAlertType: AlertTypeInitializer = ({
},
ruleParamsExpression: (params: RuleTypeParamsExpressionProps) => (
{
+ const { isDev, isServerless, coreStart, startPlugins, setupPlugins, appMountParameters } =
+ kibanaService;
+
const {
application: { capabilities },
chrome: { setBadge, setHelpExtension },
@@ -30,7 +26,7 @@ export function renderApp(
http: { basePath },
i18n,
theme,
- } = core;
+ } = kibanaService.coreStart;
const { apm, infrastructure, logs } = getIntegratedAppAvailability(
capabilities,
@@ -40,24 +36,22 @@ export function renderApp(
const canSave = (capabilities.uptime.save ?? false) as boolean; // TODO: Determine for synthetics
const darkMode = theme.getTheme().darkMode;
- const props: SyntheticsAppProps = {
+ return {
isDev,
- plugins,
+ setupPlugins,
canSave,
- core,
+ coreStart,
i18n,
startPlugins,
basePath: basePath.get(),
darkMode,
- commonlyUsedRanges: core.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES),
+ commonlyUsedRanges: coreStart.uiSettings.get(DEFAULT_TIMEPICKER_QUICK_RANGES),
isApmAvailable: apm,
isInfraAvailable: infrastructure,
isLogsAvailable: logs,
renderGlobalHelpControls: () =>
setHelpExtension({
- appName: i18nFormatter.translate('xpack.synthetics.header.appName', {
- defaultMessage: 'Synthetics',
- }),
+ appName: SYNTHETICS_APP_NAME,
links: [
{
linkType: 'documentation',
@@ -72,13 +66,21 @@ export function renderApp(
setBadge,
appMountParameters,
isServerless,
- setBreadcrumbs: startPlugins.serverless?.setBreadcrumbs ?? core.chrome.setBreadcrumbs,
+ setBreadcrumbs: startPlugins.serverless?.setBreadcrumbs ?? coreStart.chrome.setBreadcrumbs,
};
+};
+
+export function renderApp(appMountParameters: AppMountParameters) {
+ const props: SyntheticsAppProps = getSyntheticsAppProps();
ReactDOM.render(, appMountParameters.element);
return () => {
- startPlugins.data.search.session.clear();
+ props.startPlugins.data.search.session.clear();
ReactDOM.unmountComponentAtNode(appMountParameters.element);
};
}
+
+const SYNTHETICS_APP_NAME = i18nFormatter.translate('xpack.synthetics.header.appName', {
+ defaultMessage: 'Synthetics',
+});
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/monitor_list/toast_title.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/monitor_list/toast_title.tsx
index 0083a5a75339f..04c5065014289 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/monitor_list/toast_title.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/monitor_list/toast_title.tsx
@@ -11,5 +11,5 @@ import { toMountPoint } from '@kbn/react-kibana-mount';
import { kibanaService } from '../../../../utils/kibana_service';
export function toastTitle({ title, testAttribute }: { title: string; testAttribute?: string }) {
- return toMountPoint({title}
, kibanaService.core);
+ return toMountPoint({title}
, kibanaService.coreStart);
}
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/overview_status/index.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/overview_status/index.ts
index 5125e723f13db..69b735302ee75 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/overview_status/index.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/overview_status/index.ts
@@ -9,7 +9,11 @@ import { createReducer } from '@reduxjs/toolkit';
import { OverviewStatusState } from '../../../../../common/runtime_types';
import { IHttpSerializedFetchError } from '..';
-import { clearOverviewStatusErrorAction, fetchOverviewStatusAction } from './actions';
+import {
+ clearOverviewStatusErrorAction,
+ fetchOverviewStatusAction,
+ quietFetchOverviewStatusAction,
+} from './actions';
export interface OverviewStatusStateReducer {
loading: boolean;
@@ -29,6 +33,10 @@ export const overviewStatusReducer = createReducer(initialState, (builder) => {
builder
.addCase(fetchOverviewStatusAction.get, (state) => {
state.status = null;
+ state.loading = true;
+ })
+ .addCase(quietFetchOverviewStatusAction.get, (state) => {
+ state.loading = true;
})
.addCase(fetchOverviewStatusAction.success, (state, action) => {
state.status = {
@@ -36,9 +44,11 @@ export const overviewStatusReducer = createReducer(initialState, (builder) => {
allConfigs: { ...action.payload.upConfigs, ...action.payload.downConfigs },
};
state.loaded = true;
+ state.loading = false;
})
.addCase(fetchOverviewStatusAction.fail, (state, action) => {
state.error = action.payload;
+ state.loading = false;
})
.addCase(clearOverviewStatusErrorAction, (state) => {
state.error = null;
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/overview_status/selectors.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/overview_status/selectors.ts
index 07745420b86c8..c23eed413d107 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/overview_status/selectors.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/overview_status/selectors.ts
@@ -8,5 +8,5 @@
import { SyntheticsAppState } from '../root_reducer';
export const selectOverviewStatus = ({
- overviewStatus: { status, error, loaded },
-}: SyntheticsAppState) => ({ status, error, loaded });
+ overviewStatus: { status, error, loaded, loading },
+}: SyntheticsAppState) => ({ status, error, loaded, loading });
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/settings/effects.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/settings/effects.ts
index 551838a6f6ec4..fdc7c55a7a053 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/settings/effects.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/settings/effects.ts
@@ -81,13 +81,13 @@ export function* setDynamicSettingsEffect() {
yield call(setDynamicSettings, { settings: action.payload });
yield put(updateDefaultAlertingAction.get());
yield put(setDynamicSettingsAction.success(action.payload));
- kibanaService.core.notifications.toasts.addSuccess(
+ kibanaService.coreSetup.notifications.toasts.addSuccess(
i18n.translate('xpack.synthetics.settings.saveSuccess', {
defaultMessage: 'Settings saved!',
})
);
} catch (err) {
- kibanaService.core.notifications.toasts.addError(err, {
+ kibanaService.coreSetup.notifications.toasts.addError(err, {
title: couldNotSaveSettingsText,
});
yield put(setDynamicSettingsAction.fail(err));
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/utils/fetch_effect.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/utils/fetch_effect.ts
index d9412849114ab..5883c55196ff7 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/utils/fetch_effect.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/state/utils/fetch_effect.ts
@@ -67,7 +67,7 @@ export function fetchEffectFactory(
if (typeof onFailure === 'function') {
onFailure?.(error);
} else if (typeof onFailure === 'string') {
- kibanaService.core.notifications.toasts.addError(
+ kibanaService.coreSetup.notifications.toasts.addError(
{ ...error, message: serializedError.body?.message ?? error.message },
{
title: onFailure,
@@ -104,7 +104,7 @@ export function fetchEffectFactory(
if (typeof onSuccess === 'function') {
onSuccess(response as R);
} else if (onSuccess && typeof onSuccess === 'string') {
- kibanaService.core.notifications.toasts.addSuccess(onSuccess);
+ kibanaService.coreSetup.notifications.toasts.addSuccess(onSuccess);
}
}
} catch (error) {
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/synthetics_app.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/synthetics_app.tsx
index 93c45442695ad..61cf6b69763da 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/synthetics_app.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/synthetics_app.tsx
@@ -6,42 +6,30 @@
*/
import React, { useEffect } from 'react';
-import { Provider as ReduxProvider } from 'react-redux';
import { APP_WRAPPER_CLASS } from '@kbn/core/public';
import { i18n } from '@kbn/i18n';
-import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common';
-import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { InspectorContextProvider } from '@kbn/observability-shared-plugin/public';
import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render';
import { KibanaThemeProvider } from '@kbn/react-kibana-context-theme';
-import { RedirectAppLinks } from '@kbn/shared-ux-link-redirect-app';
import { Router } from '@kbn/shared-ux-router';
+import { SyntheticsSharedContext } from './contexts/synthetics_shared_context';
import { kibanaService } from '../../utils/kibana_service';
import { ActionMenu } from './components/common/header/action_menu';
import { TestNowModeFlyoutContainer } from './components/test_now_mode/test_now_mode_flyout_container';
-import {
- SyntheticsAppProps,
- SyntheticsRefreshContextProvider,
- SyntheticsSettingsContextProvider,
- SyntheticsStartupPluginsContextProvider,
- SyntheticsThemeContextProvider,
-} from './contexts';
-import { SyntheticsDataViewContextProvider } from './contexts/synthetics_data_view_context';
+import { SyntheticsAppProps, SyntheticsSettingsContextProvider } from './contexts';
import { PageRouter } from './routes';
-import { setBasePath, storage, store } from './state';
+import { setBasePath, store } from './state';
const Application = (props: SyntheticsAppProps) => {
const {
basePath,
canSave,
- core,
- darkMode,
- plugins,
+ coreStart,
+ startPlugins,
renderGlobalHelpControls,
setBadge,
- startPlugins,
appMountParameters,
} = props;
@@ -62,16 +50,17 @@ const Application = (props: SyntheticsAppProps) => {
);
}, [canSave, renderGlobalHelpControls, setBadge]);
- kibanaService.core = core;
- kibanaService.startPlugins = startPlugins;
kibanaService.theme = props.appMountParameters.theme$;
store.dispatch(setBasePath(basePath));
+ const PresentationContextProvider =
+ startPlugins.presentationUtil?.ContextProvider ?? React.Fragment;
+
return (
-
+
{
},
}}
>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx
index 552229fe47346..9d4870b8c9154 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx
+++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/utils/testing/rtl_helpers.tsx
@@ -34,10 +34,7 @@ import { MountWithReduxProvider } from './helper_with_redux';
import { AppState } from '../../state';
import { stringifyUrlParams } from '../url_params';
import { ClientPluginsStart } from '../../../../plugin';
-import {
- SyntheticsRefreshContextProvider,
- SyntheticsStartupPluginsContextProvider,
-} from '../../contexts';
+import { SyntheticsRefreshContextProvider } from '../../contexts';
import { kibanaService } from '../../../../utils/kibana_service';
type DeepPartial = {
@@ -182,21 +179,14 @@ export function MockKibanaProvider({
}: MockKibanaProviderProps) {
const coreOptions = merge({}, mockCore(), core);
- kibanaService.core = coreOptions as any;
+ kibanaService.coreStart = coreOptions as any;
return (
-
-
- {children}
-
-
+
+ {children}
+
);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/plugin.ts b/x-pack/plugins/observability_solution/synthetics/public/plugin.ts
index 50c79681a4ebc..1192b4d991f55 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/plugin.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/plugin.ts
@@ -25,7 +25,7 @@ import type {
ExploratoryViewPublicSetup,
ExploratoryViewPublicStart,
} from '@kbn/exploratory-view-plugin/public';
-import { EmbeddableStart } from '@kbn/embeddable-plugin/public';
+import { EmbeddableStart, EmbeddableSetup } from '@kbn/embeddable-plugin/public';
import {
TriggersAndActionsUIPublicPluginSetup,
TriggersAndActionsUIPublicPluginStart,
@@ -50,12 +50,18 @@ import type {
ObservabilitySharedPluginSetup,
ObservabilitySharedPluginStart,
} from '@kbn/observability-shared-plugin/public';
+
import { LicenseManagementUIPluginSetup } from '@kbn/license-management-plugin/public/plugin';
import {
ObservabilityAIAssistantPublicSetup,
ObservabilityAIAssistantPublicStart,
} from '@kbn/observability-ai-assistant-plugin/public';
import { ServerlessPluginSetup, ServerlessPluginStart } from '@kbn/serverless/public';
+import type { UiActionsSetup } from '@kbn/ui-actions-plugin/public';
+import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public';
+import { DashboardStart, DashboardSetup } from '@kbn/dashboard-plugin/public';
+import { registerSyntheticsEmbeddables } from './apps/embeddables/register_embeddables';
+import { kibanaService } from './utils/kibana_service';
import { PLUGIN } from '../common/constants/plugin';
import { OVERVIEW_ROUTE } from '../common/constants/ui';
import { locators } from './apps/locators';
@@ -72,7 +78,10 @@ export interface ClientPluginsSetup {
share: SharePluginSetup;
triggersActionsUi: TriggersAndActionsUIPublicPluginSetup;
cloud?: CloudSetup;
+ embeddable: EmbeddableSetup;
serverless?: ServerlessPluginSetup;
+ uiActions: UiActionsSetup;
+ dashboard: DashboardSetup;
}
export interface ClientPluginsStart {
@@ -102,6 +111,8 @@ export interface ClientPluginsStart {
usageCollection: UsageCollectionStart;
serverless: ServerlessPluginStart;
licenseManagement?: LicenseManagementUIPluginSetup;
+ presentationUtil: PresentationUtilPluginStart;
+ dashboard: DashboardStart;
}
export interface SyntheticsPluginServices extends Partial {
@@ -123,12 +134,25 @@ export class SyntheticsPlugin
this._packageInfo = initContext.env.packageInfo;
}
- public setup(core: CoreSetup, plugins: ClientPluginsSetup): void {
+ public setup(
+ coreSetup: CoreSetup,
+ plugins: ClientPluginsSetup
+ ): void {
locators.forEach((locator) => {
plugins.share.url.locators.create(locator);
});
- registerSyntheticsRoutesWithNavigation(core, plugins);
+ registerSyntheticsRoutesWithNavigation(coreSetup, plugins);
+
+ coreSetup.getStartServices().then(([coreStart, clientPluginsStart]) => {
+ kibanaService.init({
+ coreSetup,
+ coreStart,
+ startPlugins: clientPluginsStart,
+ isDev: this.initContext.env.mode.dev,
+ isServerless: this._isServerless,
+ });
+ });
const appKeywords = [
'Synthetics',
@@ -149,7 +173,7 @@ export class SyntheticsPlugin
];
// Register the Synthetics UI plugin
- core.application.register({
+ coreSetup.application.register({
id: 'synthetics',
euiIconType: 'logoObservability',
order: 8400,
@@ -177,23 +201,20 @@ export class SyntheticsPlugin
},
],
mount: async (params: AppMountParameters) => {
- const [coreStart, corePlugins] = await core.getStartServices();
-
+ kibanaService.appMountParameters = params;
const { renderApp } = await import('./apps/synthetics/render_app');
- return renderApp(
- coreStart,
- plugins,
- corePlugins,
- params,
- this.initContext.env.mode.dev,
- this._isServerless
- );
+ await coreSetup.getStartServices();
+
+ return renderApp(params);
},
});
+
+ registerSyntheticsEmbeddables(coreSetup, plugins);
}
public start(coreStart: CoreStart, pluginsStart: ClientPluginsStart): void {
const { triggersActionsUi } = pluginsStart;
+ setStartServices(coreStart);
setStartServices(coreStart);
diff --git a/x-pack/plugins/observability_solution/synthetics/public/utils/kibana_service/kibana_service.ts b/x-pack/plugins/observability_solution/synthetics/public/utils/kibana_service/kibana_service.ts
index 021d8c7ec3d7d..292a0e058737b 100644
--- a/x-pack/plugins/observability_solution/synthetics/public/utils/kibana_service/kibana_service.ts
+++ b/x-pack/plugins/observability_solution/synthetics/public/utils/kibana_service/kibana_service.ts
@@ -6,43 +6,46 @@
*/
import type { Observable } from 'rxjs';
-import type { CoreStart, CoreTheme } from '@kbn/core/public';
-import { ClientPluginsStart } from '../../plugin';
+import type { CoreStart, CoreTheme, CoreSetup } from '@kbn/core/public';
+import { AppMountParameters } from '@kbn/core/public';
+import { ClientPluginsSetup, ClientPluginsStart } from '../../plugin';
import { apiService } from '../api_service/api_service';
class KibanaService {
private static instance: KibanaService;
- private _core!: CoreStart;
- private _startPlugins!: ClientPluginsStart;
- private _theme!: Observable;
-
- public get core() {
- return this._core;
- }
-
- public set core(coreStart: CoreStart) {
- this._core = coreStart;
- apiService.http = this._core.http;
- }
-
- public get startPlugins() {
- return this._startPlugins;
- }
-
- public set startPlugins(startPlugins: ClientPluginsStart) {
- this._startPlugins = startPlugins;
- }
-
- public get theme() {
- return this._theme;
- }
-
- public set theme(coreTheme: Observable) {
- this._theme = coreTheme;
+ public coreStart!: CoreStart;
+ public coreSetup!: CoreSetup;
+ public theme!: Observable;
+ public setupPlugins!: ClientPluginsSetup;
+ public isDev!: boolean;
+ public isServerless!: boolean;
+ public appMountParameters!: AppMountParameters;
+ public startPlugins!: ClientPluginsStart;
+
+ public init({
+ coreSetup,
+ coreStart,
+ startPlugins,
+ isDev,
+ isServerless,
+ }: {
+ coreSetup: CoreSetup;
+ coreStart: CoreStart;
+ startPlugins: ClientPluginsStart;
+ isDev: boolean;
+ isServerless: boolean;
+ }) {
+ this.coreSetup = coreSetup;
+ this.coreStart = coreStart;
+ this.startPlugins = startPlugins;
+ this.theme = coreStart.uiSettings.get$('theme:darkMode');
+ apiService.http = coreStart.http;
+ this.isDev = isDev;
+ this.isServerless = isServerless;
}
public get toasts() {
- return this._core.notifications.toasts;
+ return this.coreStart.notifications.toasts;
}
private constructor() {}
diff --git a/x-pack/plugins/observability_solution/synthetics/tsconfig.json b/x-pack/plugins/observability_solution/synthetics/tsconfig.json
index 95ed03ba36a11..f5df3a24c8ea1 100644
--- a/x-pack/plugins/observability_solution/synthetics/tsconfig.json
+++ b/x-pack/plugins/observability_solution/synthetics/tsconfig.json
@@ -40,7 +40,6 @@
"@kbn/kibana-react-plugin",
"@kbn/i18n-react",
"@kbn/securitysolution-io-ts-utils",
- "@kbn/ui-theme",
"@kbn/es-query",
"@kbn/stack-connectors-plugin",
"@kbn/rule-data-utils",
@@ -90,7 +89,15 @@
"@kbn/react-kibana-mount",
"@kbn/react-kibana-context-render",
"@kbn/react-kibana-context-theme",
- "@kbn/search-types"
+ "@kbn/search-types",
+ "@kbn/core-lifecycle-browser",
+ "@kbn/ui-actions-browser",
+ "@kbn/presentation-publishing",
+ "@kbn/presentation-containers",
+ "@kbn/ui-actions-plugin",
+ "@kbn/presentation-util-plugin",
+ "@kbn/core-application-browser",
+ "@kbn/dashboard-plugin"
],
"exclude": ["target/**/*"]
}
diff --git a/x-pack/plugins/osquery/common/api/asset/assets.gen.ts b/x-pack/plugins/osquery/common/api/asset/assets.gen.ts
new file mode 100644
index 0000000000000..f0cc5209e13a4
--- /dev/null
+++ b/x-pack/plugins/osquery/common/api/asset/assets.gen.ts
@@ -0,0 +1,37 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+/*
+ * NOTICE: Do not edit this file manually.
+ * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
+ *
+ * info:
+ * title: Assets Schema
+ * version: 1
+ */
+
+import { z } from 'zod';
+
+import { AssetsRequestQuery } from './assets_status.gen';
+
+export type ReadAssetsStatusRequestParams = z.infer;
+export const ReadAssetsStatusRequestParams = z.object({
+ query: AssetsRequestQuery,
+});
+export type ReadAssetsStatusRequestParamsInput = z.input;
+
+export type ReadAssetsStatusResponse = z.infer;
+export const ReadAssetsStatusResponse = z.object({});
+
+export type UpdateAssetsStatusRequestParams = z.infer;
+export const UpdateAssetsStatusRequestParams = z.object({
+ query: AssetsRequestQuery,
+});
+export type UpdateAssetsStatusRequestParamsInput = z.input;
+
+export type UpdateAssetsStatusResponse = z.infer;
+export const UpdateAssetsStatusResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/asset/assets.schema.yaml b/x-pack/plugins/osquery/common/api/asset/assets.schema.yaml
index 31688b7ce66cb..2769bc188ab20 100644
--- a/x-pack/plugins/osquery/common/api/asset/assets.schema.yaml
+++ b/x-pack/plugins/osquery/common/api/asset/assets.schema.yaml
@@ -5,25 +5,41 @@ info:
paths:
/internal/osquery/assets:
get:
+ x-codegen-enabled: true
+ operationId: ReadAssetsStatus
summary: Get assets
parameters:
- - $ref: './assets_status.schema.yaml#/components/parameters/AssetsStatusRequestQueryParameter'
+ - name: query
+ in: path
+ required: true
+ schema:
+ $ref: './assets_status.schema.yaml#/components/schemas/AssetsRequestQuery'
responses:
'200':
description: OK
content:
application/json:
schema:
- $ref: './assets_status.schema.yaml#/components/schemas/SuccessResponse'
+ type: object
+ properties: {}
+ # Define properties for the success response if needed
/internal/osquery/assets/update:
post:
+ x-codegen-enabled: true
+ operationId: UpdateAssetsStatus
summary: Update assets
parameters:
- - $ref: './assets_status.schema.yaml#/components/parameters/AssetsStatusRequestQueryParameter'
+ - name: query
+ in: path
+ required: true
+ schema:
+ $ref: './assets_status.schema.yaml#/components/schemas/AssetsRequestQuery'
responses:
'200':
description: OK
content:
application/json:
schema:
- $ref: './assets_status.schema.yaml#/components/schemas/SuccessResponse'
+ type: object
+ properties: {}
+ # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/asset/assets_status.gen.ts b/x-pack/plugins/osquery/common/api/asset/assets_status.gen.ts
index 53a98b96612ea..fd3c50374943f 100644
--- a/x-pack/plugins/osquery/common/api/asset/assets_status.gen.ts
+++ b/x-pack/plugins/osquery/common/api/asset/assets_status.gen.ts
@@ -18,6 +18,3 @@ import { z } from 'zod';
export type AssetsRequestQuery = z.infer;
export const AssetsRequestQuery = z.object({});
-
-export type SuccessResponse = z.infer;
-export const SuccessResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/asset/assets_status.schema.yaml b/x-pack/plugins/osquery/common/api/asset/assets_status.schema.yaml
index 48322c1266b07..fb57329a9992d 100644
--- a/x-pack/plugins/osquery/common/api/asset/assets_status.schema.yaml
+++ b/x-pack/plugins/osquery/common/api/asset/assets_status.schema.yaml
@@ -2,19 +2,8 @@ openapi: 3.0.0
info:
title: Assets Status Schema
version: '1'
-paths: { }
+paths: {}
components:
- parameters:
- AssetsStatusRequestQueryParameter:
- name: query
- in: path
- required: true
- schema:
- $ref: '#/components/schemas/AssetsRequestQuery'
schemas:
AssetsRequestQuery:
type: object
- SuccessResponse:
- type: object
- properties: {}
- # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/fleet_wrapper.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/fleet_wrapper.gen.ts
new file mode 100644
index 0000000000000..1ecea2c4caf19
--- /dev/null
+++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/fleet_wrapper.gen.ts
@@ -0,0 +1,51 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+/*
+ * NOTICE: Do not edit this file manually.
+ * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
+ *
+ * info:
+ * title: Fleet wrapper schema
+ * version: 1
+ */
+
+import { z } from 'zod';
+
+import { Id } from '../model/schema/common_attributes.gen';
+
+export type GetAgentDetailsRequestParams = z.infer;
+export const GetAgentDetailsRequestParams = z.object({
+ id: Id,
+});
+export type GetAgentDetailsRequestParamsInput = z.input;
+
+export type GetAgentDetailsResponse = z.infer;
+export const GetAgentDetailsResponse = z.object({});
+
+export type GetAgentPackagePoliciesResponse = z.infer;
+export const GetAgentPackagePoliciesResponse = z.object({});
+
+export type GetAgentPoliciesResponse = z.infer;
+export const GetAgentPoliciesResponse = z.object({});
+
+export type GetAgentPolicyRequestParams = z.infer;
+export const GetAgentPolicyRequestParams = z.object({
+ id: Id,
+});
+export type GetAgentPolicyRequestParamsInput = z.input;
+
+export type GetAgentPolicyResponse = z.infer;
+export const GetAgentPolicyResponse = z.object({});
+export type GetAgentsRequestQuery = z.infer;
+export const GetAgentsRequestQuery = z.object({
+ query: z.object({}),
+});
+export type GetAgentsRequestQueryInput = z.input;
+
+export type GetAgentsResponse = z.infer;
+export const GetAgentsResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/fleet_wrapper.schema.yaml b/x-pack/plugins/osquery/common/api/fleet_wrapper/fleet_wrapper.schema.yaml
index 7e46e15abb825..fa5a576cb1a2e 100644
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/fleet_wrapper.schema.yaml
+++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/fleet_wrapper.schema.yaml
@@ -5,66 +5,94 @@ info:
paths:
/internal/osquery/fleet_wrapper/agents:
get:
+ x-codegen-enabled: true
+ operationId: GetAgents
summary: Get agents
parameters:
- - $ref: './get_agents.schema.yaml#/components/parameters/GetAgentsRequestQueryParameter'
+ - name: query
+ in: query
+ required: true
+ schema:
+ type: object
+ additionalProperties: true
responses:
'200':
description: OK
content:
application/json:
schema:
- $ref: './get_agents.schema.yaml#/components/schemas/SuccessResponse'
+ type: object
+ properties: {}
+ # Define properties for the success response if needed
/internal/osquery/fleet_wrapper/agents/{id}:
get:
+ x-codegen-enabled: true
+ operationId: GetAgentDetails
summary: Get Agent details
parameters:
- - $ref: './get_agent_details.schema.yaml#/components/parameters/GetAgentDetailsRequestQueryParameter'
+ - name: id
+ in: path
+ required: true
+ schema:
+ $ref: '../model/schema/common_attributes.schema.yaml#/components/schemas/Id'
responses:
'200':
description: OK
content:
application/json:
schema:
- $ref: './get_agent_details.schema.yaml#/components/schemas/SuccessResponse'
+ type: object
+ properties: {}
+ # Define properties for the success response if needed
/internal/osquery/fleet_wrapper/agent_policies:
get:
+ x-codegen-enabled: true
+ operationId: GetAgentPolicies
summary: Get Agent policies
- parameters:
- - $ref: './get_agent_policies.schema.yaml#/components/parameters/GetAgentPoliciesRequestParameter'
- - $ref: './get_agent_policies.schema.yaml#/components/parameters/GetAgentPoliciesRequestQueryParameter'
responses:
'200':
description: OK
content:
application/json:
schema:
- $ref: './get_agent_policies.schema.yaml#/components/schemas/SuccessResponse'
+ type: object
+ properties: {}
+ # Define properties for the success response if needed
/internal/osquery/fleet_wrapper/agent_policies/{id}:
get:
+ x-codegen-enabled: true
+ operationId: GetAgentPolicy
summary: Get Agent policy
parameters:
- - $ref: './get_agent_policy.schema.yaml#/components/parameters/GetAgentPolicyRequestParameter'
+ - name: id
+ in: path
+ required: true
+ schema:
+ $ref: '../model/schema/common_attributes.schema.yaml#/components/schemas/Id'
responses:
'200':
description: OK
content:
application/json:
schema:
- $ref: './get_agent_policy.schema.yaml#/components/schemas/SuccessResponse'
+ type: object
+ properties: {}
+ # Define properties for the success response if needed
/internal/osquery/fleet_wrapper/package_policies:
get:
+ x-codegen-enabled: true
+ operationId: GetAgentPackagePolicies
summary: Get Agent policy
- parameters:
- - $ref: './get_package_policies.schema.yaml#/components/parameters/GetPackagePoliciesRequestQueryParameter'
responses:
'200':
description: OK
content:
application/json:
schema:
- $ref: './get_package_policies.schema.yaml#/components/schemas/SuccessResponse'
+ type: object
+ properties: {}
+ # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.gen.ts
deleted file mode 100644
index 5d721a018205b..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.gen.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-/*
- * NOTICE: Do not edit this file manually.
- * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
- *
- * info:
- * title: Get agent details schema
- * version: 1
- */
-
-import { z } from 'zod';
-
-export type GetAgentDetailsRequestParams = z.infer;
-export const GetAgentDetailsRequestParams = z.object({});
-
-export type SuccessResponse = z.infer;
-export const SuccessResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.schema.yaml b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.schema.yaml
deleted file mode 100644
index bdf4cb3329cdf..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_details.schema.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-openapi: 3.0.0
-info:
- title: Get agent details schema
- version: '1'
-paths: { }
-components:
- parameters:
- GetAgentDetailsRequestQueryParameter:
- name: query
- in: path
- required: true
- schema:
- $ref: '#/components/schemas/GetAgentDetailsRequestParams'
- schemas:
- GetAgentDetailsRequestParams:
- type: object
- SuccessResponse:
- type: object
- properties: {}
- # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.gen.ts
deleted file mode 100644
index 875c21a600e93..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.gen.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-/*
- * NOTICE: Do not edit this file manually.
- * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
- *
- * info:
- * title: Get agent policies schema
- * version: 1
- */
-
-import { z } from 'zod';
-
-export type GetAgentPoliciesRequestParams = z.infer;
-export const GetAgentPoliciesRequestParams = z.object({});
-
-export type SuccessResponse = z.infer;
-export const SuccessResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.schema.yaml b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.schema.yaml
deleted file mode 100644
index cdfb521712674..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies.schema.yaml
+++ /dev/null
@@ -1,26 +0,0 @@
-openapi: 3.0.0
-info:
- title: Get agent policies schema
- version: '1'
-paths: { }
-components:
- parameters:
- GetAgentPoliciesRequestQueryParameter:
- name: query
- in: query
- required: true
- schema:
- $ref: '#/components/schemas/GetAgentPoliciesRequestParams'
- GetAgentPoliciesRequestParameter:
- name: query
- in: path
- required: true
- schema:
- $ref: '#/components/schemas/GetAgentPoliciesRequestParams'
- schemas:
- GetAgentPoliciesRequestParams:
- type: object
- SuccessResponse:
- type: object
- properties: {}
- # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies_route.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies_route.ts
deleted file mode 100644
index 84a68e5fbf4c7..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policies_route.ts
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import * as t from 'io-ts';
-
-export const getAgentPoliciesRequestParamsSchema = t.unknown;
-
-export type GetAgentPoliciesRequestParamsSchema = t.OutputOf<
- typeof getAgentPoliciesRequestParamsSchema
->;
-
-export const getAgentPoliciesRequestQuerySchema = t.unknown;
-
-export type GetAgentPoliciesRequestQuerySchema = t.OutputOf<
- typeof getAgentPoliciesRequestQuerySchema
->;
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.gen.ts
deleted file mode 100644
index 3f19e274761bd..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.gen.ts
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-/*
- * NOTICE: Do not edit this file manually.
- * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
- *
- * info:
- * title: Get agent policy schema
- * version: 1
- */
-
-import { z } from 'zod';
-
-import { Id } from '../model/schema/common_attributes.gen';
-
-export type GetAgentPolicyRequestParams = z.infer;
-export const GetAgentPolicyRequestParams = z.object({
- id: Id.optional(),
-});
-
-export type SuccessResponse = z.infer;
-export const SuccessResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.schema.yaml b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.schema.yaml
deleted file mode 100644
index dc4a2607bfc6b..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_policy.schema.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
-openapi: 3.0.0
-info:
- title: Get agent policy schema
- version: '1'
-paths: { }
-components:
- parameters:
- GetAgentPolicyRequestParameter:
- name: query
- in: path
- required: true
- schema:
- $ref: '#/components/schemas/GetAgentPolicyRequestParams'
- schemas:
- GetAgentPolicyRequestParams:
- type: object
- properties:
- id:
- $ref: '../model/schema/common_attributes.schema.yaml#/components/schemas/Id'
- SuccessResponse:
- type: object
- properties: {}
- # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.gen.ts
index 80adc112312a7..041aac0bf2320 100644
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.gen.ts
+++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.gen.ts
@@ -26,6 +26,3 @@ export const GetAgentStatusRequestQueryParams = z.object({
kuery: KueryOrUndefined.optional(),
policyId: Id.optional(),
});
-
-export type SuccessResponse = z.infer;
-export const SuccessResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.schema.yaml b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.schema.yaml
index e10174bee2634..af2e9307b4c12 100644
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.schema.yaml
+++ b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agent_status.schema.yaml
@@ -2,21 +2,8 @@ openapi: 3.0.0
info:
title: Get agent status schema
version: '1'
-paths: { }
+paths: {}
components:
- parameters:
- GetAgentStatusRequestQueryParameter:
- name: query
- in: query
- required: true
- schema:
- $ref: '#/components/schemas/GetAgentStatusRequestQueryParams'
- GetAgentStatusRequestParameter:
- name: query
- in: path
- required: true
- schema:
- $ref: '#/components/schemas/GetAgentStatusRequestParams'
schemas:
GetAgentStatusRequestParams:
type: object
@@ -27,7 +14,3 @@ components:
$ref: '../model/schema/common_attributes.schema.yaml#/components/schemas/KueryOrUndefined'
policyId:
$ref: '../model/schema/common_attributes.schema.yaml#/components/schemas/Id'
- SuccessResponse:
- type: object
- properties: {}
- # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.gen.ts
deleted file mode 100644
index b162bcbfd967b..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.gen.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-/*
- * NOTICE: Do not edit this file manually.
- * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
- *
- * info:
- * title: Get agents schema
- * version: 1
- */
-
-import { z } from 'zod';
-
-export type GetAgentsRequestParams = z.infer;
-export const GetAgentsRequestParams = z.object({});
-
-export type SuccessResponse = z.infer;
-export const SuccessResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.schema.yaml b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.schema.yaml
deleted file mode 100644
index c1a387512c3d3..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_agents.schema.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-openapi: 3.0.0
-info:
- title: Get agents schema
- version: '1'
-paths: { }
-components:
- parameters:
- GetAgentsRequestQueryParameter:
- name: query
- in: path
- required: true
- schema:
- $ref: '#/components/schemas/GetAgentsRequestParams'
- schemas:
- GetAgentsRequestParams:
- type: object
- SuccessResponse:
- type: object
- properties: {}
- # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.gen.ts b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.gen.ts
deleted file mode 100644
index f4c3be37371ea..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.gen.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-/*
- * NOTICE: Do not edit this file manually.
- * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
- *
- * info:
- * title: Get package policies schema
- * version: 1
- */
-
-import { z } from 'zod';
-
-export type GetPackagePoliciesRequestParams = z.infer;
-export const GetPackagePoliciesRequestParams = z.object({});
-
-export type SuccessResponse = z.infer;
-export const SuccessResponse = z.object({});
diff --git a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.schema.yaml b/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.schema.yaml
deleted file mode 100644
index 708867e8f7fa1..0000000000000
--- a/x-pack/plugins/osquery/common/api/fleet_wrapper/get_package_policies.schema.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-openapi: 3.0.0
-info:
- title: Get package policies schema
- version: '1'
-paths: { }
-components:
- parameters:
- GetPackagePoliciesRequestQueryParameter:
- name: query
- in: path
- required: true
- schema:
- $ref: '#/components/schemas/GetPackagePoliciesRequestParams'
- schemas:
- GetPackagePoliciesRequestParams:
- type: object
- SuccessResponse:
- type: object
- properties: {}
- # Define properties for the success response if needed
diff --git a/x-pack/plugins/osquery/common/api/index.ts b/x-pack/plugins/osquery/common/api/index.ts
index 681eaab583ca8..b1c42a8dc45e6 100644
--- a/x-pack/plugins/osquery/common/api/index.ts
+++ b/x-pack/plugins/osquery/common/api/index.ts
@@ -7,8 +7,7 @@
export * from './asset/get_assets_status_route';
export * from './asset/update_assets_status_route';
-export * from './fleet_wrapper/get_agent_policies_route';
-export * from './fleet_wrapper/get_agent_details_route';
+export * from './fleet_wrapper/fleet_wrapper.gen';
export * from './fleet_wrapper/get_agent_policy_route';
export * from './fleet_wrapper/get_agent_status_for_agent_policy_route';
export * from './fleet_wrapper/get_agents_route';
diff --git a/x-pack/plugins/osquery/common/api/status/privileges_check.schema.yaml b/x-pack/plugins/osquery/common/api/status/privileges_check.schema.yaml
index 2702d1bafa040..8a8267a83f336 100644
--- a/x-pack/plugins/osquery/common/api/status/privileges_check.schema.yaml
+++ b/x-pack/plugins/osquery/common/api/status/privileges_check.schema.yaml
@@ -5,6 +5,7 @@ info:
paths:
/internal/osquery/privileges_check:
get:
+ operationId: ReadPrivilegesCheck
summary: Get Osquery privileges check
responses:
'200':
@@ -13,4 +14,4 @@ paths:
application/json:
schema:
type: object
- properties: { }
+ properties: {}
diff --git a/x-pack/plugins/osquery/common/api/status/status.schema.yaml b/x-pack/plugins/osquery/common/api/status/status.schema.yaml
index 9ab4d3bd0e607..1ed1e096ba10e 100644
--- a/x-pack/plugins/osquery/common/api/status/status.schema.yaml
+++ b/x-pack/plugins/osquery/common/api/status/status.schema.yaml
@@ -5,6 +5,7 @@ info:
paths:
/internal/osquery/status:
get:
+ operationId: ReadInstallationStatus
summary: Get Osquery installation status
responses:
'200':
@@ -13,4 +14,4 @@ paths:
application/json:
schema:
type: object
- properties: { }
+ properties: {}
diff --git a/x-pack/plugins/osquery/scripts/openapi/generate.js b/x-pack/plugins/osquery/scripts/openapi/generate.js
index 35c099301e81c..018a965702c3e 100644
--- a/x-pack/plugins/osquery/scripts/openapi/generate.js
+++ b/x-pack/plugins/osquery/scripts/openapi/generate.js
@@ -17,6 +17,4 @@ generate({
rootDir: OSQUERY_ROOT,
sourceGlob: './**/*.schema.yaml',
templateName: 'zod_operation_schema',
- // TODO: Fix lint errors
- skipLinting: true,
});
diff --git a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_details.ts b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_details.ts
index b3b6539f9fc35..c1d445fd40183 100644
--- a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_details.ts
+++ b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_details.ts
@@ -6,12 +6,11 @@
*/
import type { IRouter } from '@kbn/core/server';
-import type { GetAgentDetailsRequestParamsSchema } from '../../../common/api';
-import { buildRouteValidation } from '../../utils/build_validation/route_validation';
+import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
import { API_VERSIONS } from '../../../common/constants';
import { PLUGIN_ID } from '../../../common';
import type { OsqueryAppContext } from '../../lib/osquery_app_context_services';
-import { getAgentDetailsRequestParamsSchema } from '../../../common/api';
+import { GetAgentDetailsRequestParams } from '../../../common/api';
export const getAgentDetailsRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => {
router.versioned
@@ -25,10 +24,7 @@ export const getAgentDetailsRoute = (router: IRouter, osqueryContext: OsqueryApp
version: API_VERSIONS.internal.v1,
validate: {
request: {
- params: buildRouteValidation<
- typeof getAgentDetailsRequestParamsSchema,
- GetAgentDetailsRequestParamsSchema
- >(getAgentDetailsRequestParamsSchema),
+ params: buildRouteValidationWithZod(GetAgentDetailsRequestParams),
},
},
},
@@ -38,8 +34,7 @@ export const getAgentDetailsRoute = (router: IRouter, osqueryContext: OsqueryApp
try {
agent = await osqueryContext.service
.getAgentService()
- ?.asInternalUser // @ts-expect-error update types
- ?.getAgent(request.params.id);
+ ?.asInternalUser?.getAgent(request.params.id);
} catch (err) {
return response.notFound();
}
diff --git a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policies.ts b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policies.ts
index ee80758652706..9e84410712506 100644
--- a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policies.ts
+++ b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policies.ts
@@ -11,19 +11,10 @@ import { satisfies } from 'semver';
import type { GetAgentPoliciesResponseItem, PackagePolicy } from '@kbn/fleet-plugin/common';
import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common';
import type { IRouter } from '@kbn/core/server';
-import type {
- GetAgentPoliciesRequestParamsSchema,
- GetAgentPoliciesRequestQuerySchema,
-} from '../../../common/api';
-import { buildRouteValidation } from '../../utils/build_validation/route_validation';
import { API_VERSIONS } from '../../../common/constants';
import { OSQUERY_INTEGRATION_NAME, PLUGIN_ID } from '../../../common';
import type { OsqueryAppContext } from '../../lib/osquery_app_context_services';
import { getInternalSavedObjectsClient } from '../utils';
-import {
- getAgentPoliciesRequestParamsSchema,
- getAgentPoliciesRequestQuerySchema,
-} from '../../../common/api';
export const getAgentPoliciesRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => {
router.versioned
@@ -35,18 +26,7 @@ export const getAgentPoliciesRoute = (router: IRouter, osqueryContext: OsqueryAp
.addVersion(
{
version: API_VERSIONS.internal.v1,
- validate: {
- request: {
- params: buildRouteValidation<
- typeof getAgentPoliciesRequestParamsSchema,
- GetAgentPoliciesRequestParamsSchema
- >(getAgentPoliciesRequestParamsSchema),
- query: buildRouteValidation<
- typeof getAgentPoliciesRequestQuerySchema,
- GetAgentPoliciesRequestQuerySchema
- >(getAgentPoliciesRequestQuerySchema),
- },
- },
+ validate: {},
},
async (context, request, response) => {
const internalSavedObjectsClient = await getInternalSavedObjectsClient(
diff --git a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policy.ts b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policy.ts
index 85de68f7e44d9..bad5b01289d52 100644
--- a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policy.ts
+++ b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_agent_policy.ts
@@ -6,13 +6,12 @@
*/
import type { IRouter } from '@kbn/core/server';
-import type { GetAgentPolicyRequestParamsSchema } from '../../../common/api';
-import { buildRouteValidation } from '../../utils/build_validation/route_validation';
+import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
import { API_VERSIONS } from '../../../common/constants';
import { PLUGIN_ID } from '../../../common';
import type { OsqueryAppContext } from '../../lib/osquery_app_context_services';
import { getInternalSavedObjectsClient } from '../utils';
-import { getAgentPolicyRequestParamsSchema } from '../../../common/api';
+import { GetAgentPolicyRequestParams } from '../../../common/api';
export const getAgentPolicyRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => {
router.versioned
@@ -26,10 +25,7 @@ export const getAgentPolicyRoute = (router: IRouter, osqueryContext: OsqueryAppC
version: API_VERSIONS.internal.v1,
validate: {
request: {
- params: buildRouteValidation<
- typeof getAgentPolicyRequestParamsSchema,
- GetAgentPolicyRequestParamsSchema
- >(getAgentPolicyRequestParamsSchema),
+ params: buildRouteValidationWithZod(GetAgentPolicyRequestParams),
},
},
},
diff --git a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_package_policies.ts b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_package_policies.ts
index 887fa4811e73e..86719125b97eb 100644
--- a/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_package_policies.ts
+++ b/x-pack/plugins/osquery/server/routes/fleet_wrapper/get_package_policies.ts
@@ -7,13 +7,10 @@
import type { IRouter } from '@kbn/core/server';
import { PACKAGE_POLICY_SAVED_OBJECT_TYPE } from '@kbn/fleet-plugin/common';
-import type { GetPackagePoliciesRequestQuerySchema } from '../../../common/api';
-import { buildRouteValidation } from '../../utils/build_validation/route_validation';
import { API_VERSIONS } from '../../../common/constants';
import { PLUGIN_ID, OSQUERY_INTEGRATION_NAME } from '../../../common';
import type { OsqueryAppContext } from '../../lib/osquery_app_context_services';
import { getInternalSavedObjectsClient } from '../utils';
-import { getPackagePoliciesRequestQuerySchema } from '../../../common/api';
export const getPackagePoliciesRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => {
router.versioned
@@ -25,14 +22,7 @@ export const getPackagePoliciesRoute = (router: IRouter, osqueryContext: Osquery
.addVersion(
{
version: API_VERSIONS.internal.v1,
- validate: {
- request: {
- query: buildRouteValidation<
- typeof getPackagePoliciesRequestQuerySchema,
- GetPackagePoliciesRequestQuerySchema
- >(getPackagePoliciesRequestQuerySchema),
- },
- },
+ validate: {},
},
async (context, request, response) => {
const internalSavedObjectsClient = await getInternalSavedObjectsClient(
diff --git a/x-pack/plugins/osquery/tsconfig.json b/x-pack/plugins/osquery/tsconfig.json
index 6d713311c777d..6cc74e9733a92 100644
--- a/x-pack/plugins/osquery/tsconfig.json
+++ b/x-pack/plugins/osquery/tsconfig.json
@@ -3,9 +3,7 @@
"compilerOptions": {
"outDir": "target/types"
},
- "exclude": [
- "target/**/*"
- ],
+ "exclude": ["target/**/*"],
"include": [
// add all the folders contains files to be compiled
"common/**/*",
@@ -77,6 +75,7 @@
"@kbn/openapi-generator",
"@kbn/code-editor",
"@kbn/search-types",
- "@kbn/react-kibana-context-render"
+ "@kbn/react-kibana-context-render",
+ "@kbn/zod-helpers"
]
}
diff --git a/x-pack/plugins/search_playground/public/components/summarization_panel/instructions_field.tsx b/x-pack/plugins/search_playground/public/components/summarization_panel/instructions_field.tsx
index 5db2dcc6c6d86..0bf870202f1e9 100644
--- a/x-pack/plugins/search_playground/public/components/summarization_panel/instructions_field.tsx
+++ b/x-pack/plugins/search_playground/public/components/summarization_panel/instructions_field.tsx
@@ -56,6 +56,7 @@ export const InstructionsField: React.FC = ({ value, onC
fullWidth
>
{
it('renders correctly with models', () => {
const models = [
{
+ id: 'model1',
name: 'Model1',
disabled: false,
icon: MockIcon,
@@ -47,6 +48,7 @@ describe('SummarizationModel', () => {
connectorType: LLMs.openai_azure,
},
{
+ id: 'model2',
name: 'Model2',
disabled: true,
icon: MockIcon,
diff --git a/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx b/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx
index 996d963eaeb16..b31512177d3cb 100644
--- a/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx
+++ b/x-pack/plugins/search_playground/public/hooks/use_source_indices_fields.test.tsx
@@ -23,9 +23,17 @@ let formHookSpy: jest.SpyInstance;
import { useSourceIndicesFields } from './use_source_indices_field';
import { IndicesQuerySourceFields } from '../types';
-describe('useSourceIndicesFields Hook', () => {
+// Failing: See https://github.com/elastic/kibana/issues/188840
+describe.skip('useSourceIndicesFields Hook', () => {
let postMock: jest.Mock;
+ beforeEach(() => {
+ // Playground Provider has the formProvider which
+ // persists the form state into local storage
+ // We need to clear the local storage before each test
+ localStorage.clear();
+ });
+
const wrapper = ({ children }: { children: React.ReactNode }) => (
{children}
);
diff --git a/x-pack/plugins/search_playground/public/providers/form_provider.test.tsx b/x-pack/plugins/search_playground/public/providers/form_provider.test.tsx
index 9ae9f4faac99b..73def5031615e 100644
--- a/x-pack/plugins/search_playground/public/providers/form_provider.test.tsx
+++ b/x-pack/plugins/search_playground/public/providers/form_provider.test.tsx
@@ -6,13 +6,14 @@
*/
import React from 'react';
-import { render, waitFor } from '@testing-library/react';
+import { render, waitFor, act } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
-import { FormProvider } from './form_provider';
+import { FormProvider, LOCAL_STORAGE_KEY } from './form_provider';
import { useLoadFieldsByIndices } from '../hooks/use_load_fields_by_indices';
import { useLLMsModels } from '../hooks/use_llms_models';
import * as ReactHookForm from 'react-hook-form';
import { ChatFormFields } from '../types';
+import { useSearchParams } from 'react-router-dom-v5-compat';
jest.mock('../hooks/use_load_fields_by_indices');
jest.mock('../hooks/use_llms_models');
@@ -24,6 +25,21 @@ let formHookSpy: jest.SpyInstance;
const mockUseLoadFieldsByIndices = useLoadFieldsByIndices as jest.Mock;
const mockUseLLMsModels = useLLMsModels as jest.Mock;
+const mockUseSearchParams = useSearchParams as jest.Mock;
+
+const localStorageMock = (() => {
+ let store: Record = {};
+
+ return {
+ getItem: (key: string) => store[key] || null,
+ setItem: (key: string, value: string) => {
+ store[key] = value;
+ },
+ clear: () => {
+ store = {};
+ },
+ };
+})() as Storage;
describe('FormProvider', () => {
beforeEach(() => {
@@ -34,11 +50,12 @@ describe('FormProvider', () => {
afterEach(() => {
jest.clearAllMocks();
+ localStorageMock.clear();
});
it('renders the form provider with initial values, no default model', async () => {
render(
-
+
Test Child Component
);
@@ -65,7 +82,7 @@ describe('FormProvider', () => {
mockUseLLMsModels.mockReturnValueOnce(mockModels);
render(
-
+
Test Child Component
);
@@ -88,14 +105,139 @@ describe('FormProvider', () => {
mockUseLLMsModels.mockReturnValueOnce(modelsWithAllDisabled);
render(
-
+
Test Child Component
);
await waitFor(() => {
expect(mockUseLoadFieldsByIndices).toHaveBeenCalled();
- expect(modelsWithAllDisabled.find((model) => !model.disabled)).toBeUndefined();
+ });
+
+ expect(
+ formHookSpy.mock.results[0].value.getValues(ChatFormFields.summarizationModel)
+ ).toBeUndefined();
+ });
+
+ it('saves form state to localStorage', async () => {
+ render(
+
+ Test Child Component
+
+ );
+
+ const { setValue } = formHookSpy.mock.results[0].value;
+
+ act(() => {
+ setValue(ChatFormFields.prompt, 'New prompt');
+ });
+
+ await waitFor(() => {
+ expect(localStorageMock.getItem(LOCAL_STORAGE_KEY)).toEqual(
+ JSON.stringify({
+ prompt: 'New prompt',
+ doc_size: 3,
+ source_fields: {},
+ indices: [],
+ summarization_model: undefined,
+ })
+ );
+ });
+ });
+
+ it('loads form state from localStorage', async () => {
+ localStorageMock.setItem(
+ LOCAL_STORAGE_KEY,
+ JSON.stringify({
+ prompt: 'Loaded prompt',
+ doc_size: 3,
+ source_fields: {},
+ indices: [],
+ summarization_model: undefined,
+ })
+ );
+
+ render(
+
+ Test Child Component
+
+ );
+
+ const { getValues } = formHookSpy.mock.results[0].value;
+
+ await waitFor(() => {
+ expect(getValues()).toEqual({
+ prompt: 'Loaded prompt',
+ doc_size: 3,
+ source_fields: {},
+ indices: [],
+ summarization_model: undefined,
+ });
+ });
+ });
+
+ it('overrides the session model to the default when not found in list', async () => {
+ const mockModels = [
+ { id: 'model1', name: 'Model 1', disabled: false },
+ { id: 'model2', name: 'Model 2', disabled: true },
+ ];
+
+ mockUseLLMsModels.mockReturnValueOnce(mockModels);
+
+ localStorageMock.setItem(
+ LOCAL_STORAGE_KEY,
+ JSON.stringify({
+ prompt: 'Loaded prompt',
+ doc_size: 3,
+ source_fields: {},
+ indices: [],
+ summarization_model: { id: 'non-exist-model', name: 'Model 1', disabled: false },
+ })
+ );
+
+ render(
+
+ Test Child Component
+
+ );
+
+ const { getValues } = formHookSpy.mock.results[0].value;
+
+ await waitFor(() => {
+ expect(getValues().summarization_model).toEqual({
+ id: 'model1',
+ name: 'Model 1',
+ disabled: false,
+ });
+ });
+ });
+
+ it('updates indices from search params', async () => {
+ const mockSearchParams = new URLSearchParams();
+ mockSearchParams.get = jest.fn().mockReturnValue('new-index');
+ mockUseSearchParams.mockReturnValue([mockSearchParams]);
+
+ localStorageMock.setItem(
+ LOCAL_STORAGE_KEY,
+ JSON.stringify({
+ prompt: 'Loaded prompt',
+ doc_size: 3,
+ source_fields: {},
+ indices: ['old-index'],
+ summarization_model: undefined,
+ })
+ );
+
+ render(
+
+ Test Child Component
+
+ );
+
+ const { getValues } = formHookSpy.mock.results[0].value;
+
+ await waitFor(() => {
+ expect(getValues(ChatFormFields.indices)).toEqual(['new-index']);
});
});
});
diff --git a/x-pack/plugins/search_playground/public/providers/form_provider.tsx b/x-pack/plugins/search_playground/public/providers/form_provider.tsx
index a319d15f63d20..03c0ce5652e19 100644
--- a/x-pack/plugins/search_playground/public/providers/form_provider.tsx
+++ b/x-pack/plugins/search_playground/public/providers/form_provider.tsx
@@ -11,25 +11,61 @@ import { useLoadFieldsByIndices } from '../hooks/use_load_fields_by_indices';
import { ChatForm, ChatFormFields } from '../types';
import { useLLMsModels } from '../hooks/use_llms_models';
-export const FormProvider: React.FC = ({ children }) => {
+type PartialChatForm = Partial;
+export const LOCAL_STORAGE_KEY = 'search_playground_session';
+
+const DEFAULT_FORM_VALUES: PartialChatForm = {
+ prompt: 'You are an assistant for question-answering tasks.',
+ doc_size: 3,
+ source_fields: {},
+ indices: [],
+ summarization_model: undefined,
+};
+
+const getLocalSession = (storage: Storage): PartialChatForm => {
+ try {
+ const localSessionJSON = storage.getItem(LOCAL_STORAGE_KEY);
+ const sessionState = localSessionJSON ? JSON.parse(localSessionJSON) : {};
+
+ return {
+ ...DEFAULT_FORM_VALUES,
+ ...sessionState,
+ };
+ } catch (e) {
+ return DEFAULT_FORM_VALUES;
+ }
+};
+
+const setLocalSession = (state: PartialChatForm, storage: Storage) => {
+ storage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(state));
+};
+
+interface FormProviderProps {
+ storage?: Storage;
+}
+
+export const FormProvider: React.FC = ({ children, storage = localStorage }) => {
const models = useLLMsModels();
const [searchParams] = useSearchParams();
const index = useMemo(() => searchParams.get('default-index'), [searchParams]);
+ const sessionState = useMemo(() => getLocalSession(storage), [storage]);
const form = useForm({
- defaultValues: {
- prompt: 'You are an assistant for question-answering tasks.',
- doc_size: 3,
- source_fields: {},
- indices: index ? [index] : [],
- summarization_model: undefined,
- },
+ defaultValues: { ...sessionState, indices: index ? [index] : sessionState.indices },
});
useLoadFieldsByIndices({ watch: form.watch, setValue: form.setValue, getValues: form.getValues });
+ useEffect(() => {
+ const subscription = form.watch((values) =>
+ setLocalSession(values as Partial, storage)
+ );
+ return () => subscription.unsubscribe();
+ }, [form, storage]);
+
useEffect(() => {
const defaultModel = models.find((model) => !model.disabled);
+ const currentModel = form.getValues(ChatFormFields.summarizationModel);
- if (defaultModel && !form.getValues(ChatFormFields.summarizationModel)) {
+ if (defaultModel && (!currentModel || !models.find((model) => currentModel.id === model.id))) {
form.setValue(ChatFormFields.summarizationModel, defaultModel);
}
}, [form, models]);
diff --git a/x-pack/plugins/search_playground/public/types.ts b/x-pack/plugins/search_playground/public/types.ts
index f44e354d411db..2bbd45ff16230 100644
--- a/x-pack/plugins/search_playground/public/types.ts
+++ b/x-pack/plugins/search_playground/public/types.ts
@@ -73,7 +73,7 @@ export interface ChatForm {
[ChatFormFields.citations]: boolean;
[ChatFormFields.indices]: string[];
[ChatFormFields.summarizationModel]: LLMModel;
- [ChatFormFields.elasticsearchQuery]: { retriever: unknown }; // RetrieverContainer leads to "Type instantiation is excessively deep and possibly infinite" error
+ [ChatFormFields.elasticsearchQuery]: { retriever: any }; // RetrieverContainer leads to "Type instantiation is excessively deep and possibly infinite" error
[ChatFormFields.sourceFields]: { [index: string]: string[] };
[ChatFormFields.docSize]: number;
[ChatFormFields.queryFields]: { [index: string]: string[] };
@@ -203,6 +203,7 @@ export interface UseChatHelpers {
}
export interface LLMModel {
+ id: string;
name: string;
value?: string;
showConnectorName?: boolean;
diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/index_management/create_index/create_index.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/index_management/create_index/create_index.schema.yaml
index 63213117bd9fb..b825f5f7af7c0 100644
--- a/x-pack/plugins/security_solution/common/api/detection_engine/index_management/create_index/create_index.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/detection_engine/index_management/create_index/create_index.schema.yaml
@@ -35,6 +35,7 @@ paths:
schema:
$ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse'
404:
+ description: Not found
content:
application/json:
schema:
diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/index_management/read_index/read_index.schema.yaml b/x-pack/plugins/security_solution/common/api/detection_engine/index_management/read_index/read_index.schema.yaml
index 4c38c57da7592..ddfbf564de2ac 100644
--- a/x-pack/plugins/security_solution/common/api/detection_engine/index_management/read_index/read_index.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/detection_engine/index_management/read_index/read_index.schema.yaml
@@ -38,6 +38,7 @@ paths:
schema:
$ref: '../../../model/error_responses.schema.yaml#/components/schemas/SiemErrorResponse'
404:
+ description: Not found
content:
application/json:
schema:
diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema_legacy/common_attributes.ts b/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema_legacy/common_attributes.ts
deleted file mode 100644
index ba07c49a7b130..0000000000000
--- a/x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema_legacy/common_attributes.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import * as t from 'io-ts';
-import { NonEmptyString, UUID } from '@kbn/securitysolution-io-ts-types';
-
-/*
-IMPORTANT NOTE ON THIS FILE:
-
-This file contains the remaining rule schema types created manually via io-ts. They have been
-migrated to Zod schemas created via code generation out of OpenAPI schemas
-(found in x-pack/plugins/security_solution/common/api/detection_engine/model/rule_schema/common_attributes.gen.ts)
-
-The remaining types here couldn't easily be deleted/replaced because they are dependencies in
-complex derived schemas in two files:
-
-- x-pack/plugins/security_solution/common/api/detection_engine/rule_exceptions/find_exception_references/find_exception_references_route.ts
-- x-pack/plugins/security_solution/common/api/timeline/model/api.ts
-
-Once those two files are migrated to Zod, the /common/api/detection_engine/model/rule_schema_legacy
-folder can be removed.
-*/
-
-export type RuleObjectId = t.TypeOf;
-export const RuleObjectId = UUID;
-
-/**
- * NOTE: Never make this a strict uuid, we allow the rule_id to be any string at the moment
- * in case we encounter 3rd party rule systems which might be using auto incrementing numbers
- * or other different things.
- */
-export type RuleSignatureId = t.TypeOf;
-export const RuleSignatureId = t.string; // should be non-empty string?
-
-export type RuleName = t.TypeOf;
-export const RuleName = NonEmptyString;
-
-/**
- * Outcome is a property of the saved object resolve api
- * will tell us info about the rule after 8.0 migrations
- */
-export type SavedObjectResolveOutcome = t.TypeOf;
-export const SavedObjectResolveOutcome = t.union([
- t.literal('exactMatch'),
- t.literal('aliasMatch'),
- t.literal('conflict'),
-]);
-
-export type SavedObjectResolveAliasTargetId = t.TypeOf;
-export const SavedObjectResolveAliasTargetId = t.string;
-
-export type SavedObjectResolveAliasPurpose = t.TypeOf;
-export const SavedObjectResolveAliasPurpose = t.union([
- t.literal('savedObjectConversion'),
- t.literal('savedObjectImport'),
-]);
diff --git a/x-pack/plugins/security_solution/common/api/detection_engine/rule_exceptions/find_exception_references/find_exception_references_route.ts b/x-pack/plugins/security_solution/common/api/detection_engine/rule_exceptions/find_exception_references/find_exception_references_route.ts
index cbef9a41de718..63b9363bb97c4 100644
--- a/x-pack/plugins/security_solution/common/api/detection_engine/rule_exceptions/find_exception_references/find_exception_references_route.ts
+++ b/x-pack/plugins/security_solution/common/api/detection_engine/rule_exceptions/find_exception_references/find_exception_references_route.ts
@@ -12,10 +12,17 @@ import {
list_id,
DefaultNamespaceArray,
} from '@kbn/securitysolution-io-ts-list-types';
-import { NonEmptyStringArray } from '@kbn/securitysolution-io-ts-types';
+import { NonEmptyStringArray, NonEmptyString, UUID } from '@kbn/securitysolution-io-ts-types';
+
// TODO https://github.com/elastic/security-team/issues/7491
-// eslint-disable-next-line no-restricted-imports
-import { RuleName, RuleObjectId, RuleSignatureId } from '../../model/rule_schema_legacy';
+type RuleObjectId = t.TypeOf;
+const RuleObjectId = UUID;
+
+type RuleSignatureId = t.TypeOf;
+const RuleSignatureId = t.string;
+
+type RuleName = t.TypeOf;
+const RuleName = NonEmptyString;
// If ids and list_ids are undefined, route will fetch all lists matching the
// specified namespace type
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen.ts
index c0d00e394b6b1..5315edc16ab9f 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen.ts
@@ -18,7 +18,35 @@ import { z } from 'zod';
import { CreateAssetCriticalityRecord } from './common.gen';
-export type AssetCriticalityBulkUploadRequest = z.infer;
-export const AssetCriticalityBulkUploadRequest = z.object({
+export type AssetCriticalityBulkUploadErrorItem = z.infer<
+ typeof AssetCriticalityBulkUploadErrorItem
+>;
+export const AssetCriticalityBulkUploadErrorItem = z.object({
+ message: z.string(),
+ index: z.number().int(),
+});
+
+export type AssetCriticalityBulkUploadStats = z.infer;
+export const AssetCriticalityBulkUploadStats = z.object({
+ successful: z.number().int(),
+ failed: z.number().int(),
+ total: z.number().int(),
+});
+
+export type BulkUpsertAssetCriticalityRecordsRequestBody = z.infer<
+ typeof BulkUpsertAssetCriticalityRecordsRequestBody
+>;
+export const BulkUpsertAssetCriticalityRecordsRequestBody = z.object({
records: z.array(CreateAssetCriticalityRecord).min(1).max(1000),
});
+export type BulkUpsertAssetCriticalityRecordsRequestBodyInput = z.input<
+ typeof BulkUpsertAssetCriticalityRecordsRequestBody
+>;
+
+export type BulkUpsertAssetCriticalityRecordsResponse = z.infer<
+ typeof BulkUpsertAssetCriticalityRecordsResponse
+>;
+export const BulkUpsertAssetCriticalityRecordsResponse = z.object({
+ errors: z.array(AssetCriticalityBulkUploadErrorItem),
+ stats: AssetCriticalityBulkUploadStats,
+});
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.schema.yaml
index b4b7d5d2f1fe4..c0fecede6da72 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.schema.yaml
@@ -13,40 +13,82 @@ paths:
/api/asset_criticality/bulk:
post:
x-labels: [ess, serverless]
+ x-codegen-enabled: true
+ operationId: BulkUpsertAssetCriticalityRecords
summary: Bulk upsert asset criticality data, creating or updating records as needed
requestBody:
content:
application/json:
schema:
- $ref: '#/components/schemas/AssetCriticalityBulkUploadRequest'
-
+ type: object
+ example:
+ records:
+ - id_value: 'host-1'
+ id_field: 'host.name'
+ criticality_level: 'low_impact'
+ - id_value: 'host-2'
+ id_field: 'host.name'
+ criticality_level: 'medium_impact'
+ properties:
+ records:
+ type: array
+ minItems: 1
+ maxItems: 1000
+ items:
+ $ref: './common.schema.yaml#/components/schemas/CreateAssetCriticalityRecord'
+ required:
+ - records
responses:
'200':
description: Bulk upload successful
content:
application/json:
schema:
- $ref: './common.schema.yaml#/components/schemas/AssetCriticalityBulkUploadResponse'
+ type: object
+ example:
+ errors:
+ - message: 'Invalid ID field'
+ index: 0
+ stats:
+ successful: 1
+ failed: 1
+ total: 2
+ properties:
+ errors:
+ type: array
+ items:
+ $ref: '#/components/schemas/AssetCriticalityBulkUploadErrorItem'
+ stats:
+ $ref: '#/components/schemas/AssetCriticalityBulkUploadStats'
+ required:
+ - errors
+ - stats
'413':
description: File too large
+
components:
schemas:
- AssetCriticalityBulkUploadRequest:
+ AssetCriticalityBulkUploadErrorItem:
type: object
- example:
- records:
- - id_value: 'host-1'
- id_field: 'host.name'
- criticality_level: 'low_impact'
- - id_value: 'host-2'
- id_field: 'host.name'
- criticality_level: 'medium_impact'
properties:
- records:
- type: array
- minItems: 1
- maxItems: 1000
- items:
- $ref: './common.schema.yaml#/components/schemas/CreateAssetCriticalityRecord'
+ message:
+ type: string
+ index:
+ type: integer
required:
- - records
+ - message
+ - index
+
+ AssetCriticalityBulkUploadStats:
+ type: object
+ properties:
+ successful:
+ type: integer
+ failed:
+ type: integer
+ total:
+ type: integer
+ required:
+ - successful
+ - failed
+ - total
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.gen.ts
index 4b689d22944e1..dfaa5d852c993 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.gen.ts
@@ -53,28 +53,6 @@ export const CreateAssetCriticalityRecord = AssetCriticalityRecordIdParts.merge(
})
);
-export type CreateSingleAssetCriticalityRequest = z.infer<
- typeof CreateSingleAssetCriticalityRequest
->;
-export const CreateSingleAssetCriticalityRequest = CreateAssetCriticalityRecord.merge(
- z.object({
- /**
- * If 'wait_for' the request will wait for the index refresh.
- */
- refresh: z.literal('wait_for').optional(),
- })
-);
-
-export type DeleteAssetCriticalityRecord = z.infer;
-export const DeleteAssetCriticalityRecord = AssetCriticalityRecordIdParts.merge(
- z.object({
- /**
- * If 'wait_for' the request will wait for the index refresh.
- */
- refresh: z.literal('wait_for').optional(),
- })
-);
-
export type AssetCriticalityRecord = z.infer;
export const AssetCriticalityRecord = CreateAssetCriticalityRecord.merge(
z.object({
@@ -84,24 +62,3 @@ export const AssetCriticalityRecord = CreateAssetCriticalityRecord.merge(
'@timestamp': z.string().datetime(),
})
);
-
-export type AssetCriticalityBulkUploadErrorItem = z.infer<
- typeof AssetCriticalityBulkUploadErrorItem
->;
-export const AssetCriticalityBulkUploadErrorItem = z.object({
- message: z.string(),
- index: z.number().int(),
-});
-
-export type AssetCriticalityBulkUploadStats = z.infer;
-export const AssetCriticalityBulkUploadStats = z.object({
- successful: z.number().int(),
- failed: z.number().int(),
- total: z.number().int(),
-});
-
-export type AssetCriticalityBulkUploadResponse = z.infer;
-export const AssetCriticalityBulkUploadResponse = z.object({
- errors: z.array(AssetCriticalityBulkUploadErrorItem),
- stats: AssetCriticalityBulkUploadStats,
-});
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.schema.yaml
index 3218ec07e0fe2..8d3e05ab59bac 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/common.schema.yaml
@@ -58,24 +58,6 @@ components:
$ref: '#/components/schemas/AssetCriticalityLevel'
required:
- criticality_level
- CreateSingleAssetCriticalityRequest:
- allOf:
- - $ref: '#/components/schemas/CreateAssetCriticalityRecord'
- - type: object
- properties:
- refresh:
- type: string
- enum: [wait_for]
- description: If 'wait_for' the request will wait for the index refresh.
- DeleteAssetCriticalityRecord:
- allOf:
- - $ref: '#/components/schemas/AssetCriticalityRecordIdParts'
- - type: object
- properties:
- refresh:
- type: string
- enum: [wait_for]
- description: If 'wait_for' the request will wait for the index refresh.
AssetCriticalityRecord:
allOf:
- $ref: '#/components/schemas/CreateAssetCriticalityRecord'
@@ -88,46 +70,3 @@ components:
description: The time the record was created or updated.
required:
- '@timestamp'
- AssetCriticalityBulkUploadErrorItem:
- type: object
- properties:
- message:
- type: string
- index:
- type: integer
- required:
- - message
- - index
- AssetCriticalityBulkUploadStats:
- type: object
- properties:
- successful:
- type: integer
- failed:
- type: integer
- total:
- type: integer
- required:
- - successful
- - failed
- - total
- AssetCriticalityBulkUploadResponse:
- type: object
- example:
- errors:
- - message: 'Invalid ID field'
- index: 0
- stats:
- successful: 1
- failed: 1
- total: 2
- properties:
- errors:
- type: array
- items:
- $ref: '#/components/schemas/AssetCriticalityBulkUploadErrorItem'
- stats:
- $ref: '#/components/schemas/AssetCriticalityBulkUploadStats'
- required:
- - errors
- - stats
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.gen.ts
new file mode 100644
index 0000000000000..4836f4fe844dd
--- /dev/null
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.gen.ts
@@ -0,0 +1,59 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+/*
+ * NOTICE: Do not edit this file manually.
+ * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
+ *
+ * info:
+ * title: Asset Criticality Create Record Schema
+ * version: 1
+ */
+
+import { z } from 'zod';
+
+import { CreateAssetCriticalityRecord, AssetCriticalityRecord } from './common.gen';
+
+export type CreateAssetCriticalityRecordRequestBody = z.infer<
+ typeof CreateAssetCriticalityRecordRequestBody
+>;
+export const CreateAssetCriticalityRecordRequestBody = CreateAssetCriticalityRecord.merge(
+ z.object({
+ /**
+ * If 'wait_for' the request will wait for the index refresh.
+ */
+ refresh: z.literal('wait_for').optional(),
+ })
+);
+export type CreateAssetCriticalityRecordRequestBodyInput = z.input<
+ typeof CreateAssetCriticalityRecordRequestBody
+>;
+
+export type CreateAssetCriticalityRecordResponse = z.infer<
+ typeof CreateAssetCriticalityRecordResponse
+>;
+export const CreateAssetCriticalityRecordResponse = AssetCriticalityRecord;
+
+export type InternalCreateAssetCriticalityRecordRequestBody = z.infer<
+ typeof InternalCreateAssetCriticalityRecordRequestBody
+>;
+export const InternalCreateAssetCriticalityRecordRequestBody = CreateAssetCriticalityRecord.merge(
+ z.object({
+ /**
+ * If 'wait_for' the request will wait for the index refresh.
+ */
+ refresh: z.literal('wait_for').optional(),
+ })
+);
+export type InternalCreateAssetCriticalityRecordRequestBodyInput = z.input<
+ typeof InternalCreateAssetCriticalityRecordRequestBody
+>;
+
+export type InternalCreateAssetCriticalityRecordResponse = z.infer<
+ typeof InternalCreateAssetCriticalityRecordResponse
+>;
+export const InternalCreateAssetCriticalityRecordResponse = AssetCriticalityRecord;
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml
index d59ce99c8717c..3d0bbf108d95f 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/create_asset_criticality.schema.yaml
@@ -14,14 +14,23 @@ paths:
post:
x-labels: [ess, serverless]
x-internal: true
- operationId: AssetCriticalityCreateRecord
+ x-codegen-enabled: true
+ operationId: InternalCreateAssetCriticalityRecord
summary: Deprecated Internal Create Criticality Record
+ deprecated: true
requestBody:
required: true
content:
application/json:
schema:
- $ref: './common.schema.yaml#/components/schemas/CreateSingleAssetCriticalityRequest'
+ allOf:
+ - $ref: './common.schema.yaml#/components/schemas/CreateAssetCriticalityRecord'
+ - type: object
+ properties:
+ refresh:
+ type: string
+ enum: [wait_for]
+ description: If 'wait_for' the request will wait for the index refresh.
responses:
'200':
description: Successful response
@@ -34,14 +43,22 @@ paths:
/api/asset_criticality:
post:
x-labels: [ess, serverless]
- operationId: AssetCriticalityCreateRecord
+ x-codegen-enabled: true
+ operationId: CreateAssetCriticalityRecord
summary: Create Criticality Record
requestBody:
required: true
content:
application/json:
schema:
- $ref: './common.schema.yaml#/components/schemas/CreateSingleAssetCriticalityRequest'
+ allOf:
+ - $ref: './common.schema.yaml#/components/schemas/CreateAssetCriticalityRecord'
+ - type: object
+ properties:
+ refresh:
+ type: string
+ enum: [wait_for]
+ description: If 'wait_for' the request will wait for the index refresh.
responses:
'200':
description: Successful response
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.gen.ts
new file mode 100644
index 0000000000000..fe290a67c6634
--- /dev/null
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.gen.ts
@@ -0,0 +1,61 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+/*
+ * NOTICE: Do not edit this file manually.
+ * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
+ *
+ * info:
+ * title: Asset Criticality Delete Record Schema
+ * version: 1
+ */
+
+import { z } from 'zod';
+
+import { IdField } from './common.gen';
+
+export type DeleteAssetCriticalityRecordRequestQuery = z.infer<
+ typeof DeleteAssetCriticalityRecordRequestQuery
+>;
+export const DeleteAssetCriticalityRecordRequestQuery = z.object({
+ /**
+ * The ID value of the asset.
+ */
+ id_value: z.string(),
+ /**
+ * The field representing the ID.
+ */
+ id_field: IdField,
+ /**
+ * If 'wait_for' the request will wait for the index refresh.
+ */
+ refresh: z.literal('wait_for').optional(),
+});
+export type DeleteAssetCriticalityRecordRequestQueryInput = z.input<
+ typeof DeleteAssetCriticalityRecordRequestQuery
+>;
+
+export type InternalDeleteAssetCriticalityRecordRequestQuery = z.infer<
+ typeof InternalDeleteAssetCriticalityRecordRequestQuery
+>;
+export const InternalDeleteAssetCriticalityRecordRequestQuery = z.object({
+ /**
+ * The ID value of the asset.
+ */
+ id_value: z.string(),
+ /**
+ * The field representing the ID.
+ */
+ id_field: IdField,
+ /**
+ * If 'wait_for' the request will wait for the index refresh.
+ */
+ refresh: z.literal('wait_for').optional(),
+});
+export type InternalDeleteAssetCriticalityRecordRequestQueryInput = z.input<
+ typeof InternalDeleteAssetCriticalityRecordRequestQuery
+>;
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml
index 94e1cc82e15ad..d66a2283596c0 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/delete_asset_criticality.schema.yaml
@@ -14,11 +14,31 @@ paths:
delete:
x-labels: [ess, serverless]
x-internal: true
- operationId: AssetCriticalityDeleteRecord
+ x-codegen-enabled: true
+ operationId: InternalDeleteAssetCriticalityRecord
summary: Deprecated Internal Delete Criticality Record
+ deprecated: true
parameters:
- - $ref: './common.schema.yaml#/components/parameters/id_value'
- - $ref: './common.schema.yaml#/components/parameters/id_field'
+ - name: id_value
+ in: query
+ required: true
+ schema:
+ type: string
+ description: The ID value of the asset.
+ - name: id_field
+ in: query
+ required: true
+ schema:
+ $ref: './common.schema.yaml#/components/schemas/IdField'
+ example: 'host.name'
+ description: The field representing the ID.
+ - name: refresh
+ in: query
+ required: false
+ schema:
+ type: string
+ enum: [wait_for]
+ description: If 'wait_for' the request will wait for the index refresh.
responses:
'200':
description: Successful response
@@ -27,11 +47,30 @@ paths:
/api/asset_criticality:
delete:
x-labels: [ess, serverless]
- operationId: AssetCriticalityDeleteRecord
+ x-codegen-enabled: true
+ operationId: DeleteAssetCriticalityRecord
summary: Delete Criticality Record
parameters:
- - $ref: './common.schema.yaml#/components/parameters/id_value'
- - $ref: './common.schema.yaml#/components/parameters/id_field'
+ - name: id_value
+ in: query
+ required: true
+ schema:
+ type: string
+ description: The ID value of the asset.
+ - name: id_field
+ in: query
+ required: true
+ schema:
+ $ref: './common.schema.yaml#/components/schemas/IdField'
+ example: 'host.name'
+ description: The field representing the ID.
+ - name: refresh
+ in: query
+ required: false
+ schema:
+ type: string
+ enum: [wait_for]
+ description: If 'wait_for' the request will wait for the index refresh.
responses:
'200':
description: Successful response
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.gen.ts
new file mode 100644
index 0000000000000..7437960ef9cae
--- /dev/null
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.gen.ts
@@ -0,0 +1,39 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+/*
+ * NOTICE: Do not edit this file manually.
+ * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
+ *
+ * info:
+ * title: Asset Criticality Get Record Schema
+ * version: 1
+ */
+
+import { z } from 'zod';
+
+import { IdField, AssetCriticalityRecord } from './common.gen';
+
+export type GetAssetCriticalityRecordRequestQuery = z.infer<
+ typeof GetAssetCriticalityRecordRequestQuery
+>;
+export const GetAssetCriticalityRecordRequestQuery = z.object({
+ /**
+ * The ID value of the asset.
+ */
+ id_value: z.string(),
+ /**
+ * The field representing the ID.
+ */
+ id_field: IdField,
+});
+export type GetAssetCriticalityRecordRequestQueryInput = z.input<
+ typeof GetAssetCriticalityRecordRequestQuery
+>;
+
+export type GetAssetCriticalityRecordResponse = z.infer;
+export const GetAssetCriticalityRecordResponse = AssetCriticalityRecord;
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml
index 56f3e37de1126..ca2784c48653d 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality.schema.yaml
@@ -14,11 +14,23 @@ paths:
get:
x-labels: [ess, serverless]
x-internal: true
- operationId: AssetCriticalityGetRecord
+ operationId: InternalGetAssetCriticalityRecord
summary: Deprecated Internal Get Criticality Record
+ deprecated: true
parameters:
- - $ref: './common.schema.yaml#/components/parameters/id_value'
- - $ref: './common.schema.yaml#/components/parameters/id_field'
+ - name: id_value
+ in: query
+ required: true
+ schema:
+ type: string
+ description: The ID value of the asset.
+ - name: id_field
+ in: query
+ required: true
+ schema:
+ $ref: './common.schema.yaml#/components/schemas/IdField'
+ example: 'host.name'
+ description: The field representing the ID.
responses:
'200':
description: Successful response
@@ -33,11 +45,23 @@ paths:
/api/asset_criticality:
get:
x-labels: [ess, serverless]
- operationId: AssetCriticalityGetRecord
+ x-codegen-enabled: true
+ operationId: GetAssetCriticalityRecord
summary: Get Criticality Record
parameters:
- - $ref: './common.schema.yaml#/components/parameters/id_value'
- - $ref: './common.schema.yaml#/components/parameters/id_field'
+ - name: id_value
+ in: query
+ required: true
+ schema:
+ type: string
+ description: The ID value of the asset.
+ - name: id_field
+ in: query
+ required: true
+ schema:
+ $ref: './common.schema.yaml#/components/schemas/IdField'
+ example: 'host.name'
+ description: The field representing the ID.
responses:
'200':
description: Successful response
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.gen.ts
index bb51693825def..f9d24b61bbef0 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.gen.ts
@@ -16,7 +16,7 @@
import { z } from 'zod';
-export type AssetCriticalityStatusResponse = z.infer;
-export const AssetCriticalityStatusResponse = z.object({
+export type GetAssetCriticalityStatusResponse = z.infer;
+export const GetAssetCriticalityStatusResponse = z.object({
asset_criticality_resources_installed: z.boolean().optional(),
});
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.schema.yaml
index 4052ad8f07177..f8f5dcb7c8ecd 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/get_asset_criticality_status.schema.yaml
@@ -14,7 +14,8 @@ paths:
get:
x-labels: [ess, serverless]
x-internal: true
- operationId: AssetCriticalityGetStatus
+ x-codegen-enabled: true
+ operationId: GetAssetCriticalityStatus
summary: Get Asset Criticality Status
responses:
'200':
@@ -22,14 +23,9 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/AssetCriticalityStatusResponse'
+ type: object
+ properties:
+ asset_criticality_resources_installed:
+ type: boolean
'400':
description: Invalid request
-
-components:
- schemas:
- AssetCriticalityStatusResponse:
- type: object
- properties:
- asset_criticality_resources_installed:
- type: boolean
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/index.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/index.ts
index 326a20d6c66a7..fb99a69f49f92 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/index.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/index.ts
@@ -9,5 +9,5 @@ export * from './common.gen';
export * from './get_asset_criticality_status.gen';
export * from './get_asset_criticality_privileges.gen';
export * from './bulk_upload_asset_criticality.gen';
+export * from './upload_asset_criticality_csv.gen';
export * from './list_asset_criticality.gen';
-export * from './list_asset_criticality_query_params';
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality.gen.ts
index 9cf2f7ca7c628..e17a2b006896c 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality.gen.ts
@@ -18,8 +18,39 @@ import { z } from 'zod';
import { AssetCriticalityRecord } from './common.gen';
-export type AssetCriticalityListResponse = z.infer;
-export const AssetCriticalityListResponse = z.object({
+export type FindAssetCriticalityRecordsRequestQuery = z.infer<
+ typeof FindAssetCriticalityRecordsRequestQuery
+>;
+export const FindAssetCriticalityRecordsRequestQuery = z.object({
+ /**
+ * The field to sort by.
+ */
+ sort_field: z.enum(['id_value', 'id_field', 'criticality_level', '@timestamp']).optional(),
+ /**
+ * The order to sort by.
+ */
+ sort_direction: z.enum(['asc', 'desc']).optional(),
+ /**
+ * The page number to return.
+ */
+ page: z.coerce.number().int().min(1).optional(),
+ /**
+ * The number of records to return per page.
+ */
+ per_page: z.coerce.number().int().min(1).max(1000).optional(),
+ /**
+ * The kuery to filter by.
+ */
+ kuery: z.string().optional(),
+});
+export type FindAssetCriticalityRecordsRequestQueryInput = z.input<
+ typeof FindAssetCriticalityRecordsRequestQuery
+>;
+
+export type FindAssetCriticalityRecordsResponse = z.infer<
+ typeof FindAssetCriticalityRecordsResponse
+>;
+export const FindAssetCriticalityRecordsResponse = z.object({
records: z.array(AssetCriticalityRecord),
page: z.number().int().min(1),
per_page: z.number().int().min(1).max(1000),
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality.schema.yaml
index 7c9a28c4eeaaf..34c5b98a4617f 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality.schema.yaml
@@ -13,6 +13,8 @@ paths:
/api/asset_criticality/list:
post:
x-labels: [ess, serverless]
+ x-codegen-enabled: true
+ operationId: FindAssetCriticalityRecords
summary: List asset criticality data, filtering and sorting as needed
parameters:
- name: sort_field
@@ -26,7 +28,7 @@ paths:
- criticality_level
- \@timestamp
description: The field to sort by.
- - name: sort_order
+ - name: sort_direction
in: query
required: false
schema:
@@ -62,31 +64,24 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/AssetCriticalityListResponse'
-
-components:
- schemas:
- AssetCriticalityListResponse:
- type: object
- properties:
- records:
- type: array
- items:
- $ref: './common.schema.yaml#/components/schemas/AssetCriticalityRecord'
- page:
- type: integer
- minimum: 1
- per_page:
- type: integer
- minimum: 1
- maximum: 1000
- total:
- type: integer
- minimum: 0
- required:
- - records
- - page
- - per_page
- - total
-
-
\ No newline at end of file
+ type: object
+ properties:
+ records:
+ type: array
+ items:
+ $ref: './common.schema.yaml#/components/schemas/AssetCriticalityRecord'
+ page:
+ type: integer
+ minimum: 1
+ per_page:
+ type: integer
+ minimum: 1
+ maximum: 1000
+ total:
+ type: integer
+ minimum: 0
+ required:
+ - records
+ - page
+ - per_page
+ - total
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality_query_params.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality_query_params.ts
deleted file mode 100644
index b70393056c48f..0000000000000
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/list_asset_criticality_query_params.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
- * or more contributor license agreements. Licensed under the Elastic License
- * 2.0; you may not use this file except in compliance with the Elastic License
- * 2.0.
- */
-
-import { z } from 'zod';
-
-export const ListAssetCriticalityQueryParams = z.object({
- page: z.coerce.number().min(1).optional(),
- per_page: z.coerce.number().min(1).max(10000).optional(),
- sort_field: z.enum(['id_field', 'id_value', '@timestamp', 'criticality_level']).optional(),
- sort_direction: z.enum(['asc', 'desc']).optional(),
- kuery: z.string().optional(),
-});
-
-export type ListAssetCriticalityQueryParams = z.infer;
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen.ts
new file mode 100644
index 0000000000000..4282056378426
--- /dev/null
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen.ts
@@ -0,0 +1,46 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+/*
+ * NOTICE: Do not edit this file manually.
+ * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
+ *
+ * info:
+ * title: Asset Criticality CSV Upload Schema
+ * version: 1
+ */
+
+import { z } from 'zod';
+
+export type AssetCriticalityCsvUploadErrorItem = z.infer;
+export const AssetCriticalityCsvUploadErrorItem = z.object({
+ message: z.string(),
+ index: z.number().int(),
+});
+
+export type AssetCriticalityCsvUploadStats = z.infer;
+export const AssetCriticalityCsvUploadStats = z.object({
+ successful: z.number().int(),
+ failed: z.number().int(),
+ total: z.number().int(),
+});
+
+export type InternalUploadAssetCriticalityRecordsResponse = z.infer<
+ typeof InternalUploadAssetCriticalityRecordsResponse
+>;
+export const InternalUploadAssetCriticalityRecordsResponse = z.object({
+ errors: z.array(AssetCriticalityCsvUploadErrorItem),
+ stats: AssetCriticalityCsvUploadStats,
+});
+
+export type UploadAssetCriticalityRecordsResponse = z.infer<
+ typeof UploadAssetCriticalityRecordsResponse
+>;
+export const UploadAssetCriticalityRecordsResponse = z.object({
+ errors: z.array(AssetCriticalityCsvUploadErrorItem),
+ stats: AssetCriticalityCsvUploadStats,
+});
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml
index c348dcefa8b78..77e78f5c6d4d3 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.schema.yaml
@@ -14,7 +14,10 @@ paths:
post:
x-labels: [ess, serverless]
x-internal: true
+ x-codegen-enabled: true
+ operationId: InternalUploadAssetCriticalityRecords
summary: Deprecated internal API which Uploads a CSV file containing asset criticality data
+ deprecated: true
requestBody:
content:
multipart/form-data:
@@ -33,13 +36,33 @@ paths:
content:
application/json:
schema:
- $ref: '#./common/components/schemas/AssetCriticalityBulkUploadResponse'
+ type: object
+ example:
+ errors:
+ - message: 'Invalid ID field'
+ index: 0
+ stats:
+ successful: 1
+ failed: 1
+ total: 2
+ properties:
+ errors:
+ type: array
+ items:
+ $ref: '#/components/schemas/AssetCriticalityCsvUploadErrorItem'
+ stats:
+ $ref: '#/components/schemas/AssetCriticalityCsvUploadStats'
+ required:
+ - errors
+ - stats
'413':
description: File too large
/api/asset_criticality/upload_csv:
post:
x-labels: [ess, serverless]
x-internal: true
+ x-codegen-enabled: true
+ operationId: UploadAssetCriticalityRecords
summary: Uploads a CSV file containing asset criticality data
requestBody:
content:
@@ -59,6 +82,51 @@ paths:
content:
application/json:
schema:
- $ref: '#./common/components/schemas/AssetCriticalityBulkUploadResponse'
+ type: object
+ example:
+ errors:
+ - message: 'Invalid ID field'
+ index: 0
+ stats:
+ successful: 1
+ failed: 1
+ total: 2
+ properties:
+ errors:
+ type: array
+ items:
+ $ref: '#/components/schemas/AssetCriticalityCsvUploadErrorItem'
+ stats:
+ $ref: '#/components/schemas/AssetCriticalityCsvUploadStats'
+ required:
+ - errors
+ - stats
'413':
description: File too large
+
+components:
+ schemas:
+ AssetCriticalityCsvUploadErrorItem:
+ type: object
+ properties:
+ message:
+ type: string
+ index:
+ type: integer
+ required:
+ - message
+ - index
+
+ AssetCriticalityCsvUploadStats:
+ type: object
+ properties:
+ successful:
+ type: integer
+ failed:
+ type: integer
+ total:
+ type: integer
+ required:
+ - successful
+ - failed
+ - total
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_disable_route.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_disable_route.gen.ts
index 620620c95b888..b50eb00db6301 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_disable_route.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_disable_route.gen.ts
@@ -16,13 +16,13 @@
import { z } from 'zod';
-export type RiskEngineDisableResponse = z.infer;
-export const RiskEngineDisableResponse = z.object({
- success: z.boolean().optional(),
-});
-
export type RiskEngineDisableErrorResponse = z.infer;
export const RiskEngineDisableErrorResponse = z.object({
message: z.string(),
full_error: z.string(),
});
+
+export type DisableRiskEngineResponse = z.infer;
+export const DisableRiskEngineResponse = z.object({
+ success: z.boolean().optional(),
+});
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_disable_route.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_disable_route.schema.yaml
index 33f35aa1bef1b..c491ec74e2a50 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_disable_route.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_disable_route.schema.yaml
@@ -18,6 +18,8 @@ paths:
post:
x-labels: [ess, serverless]
x-internal: true
+ x-codegen-enabled: true
+ operationId: DisableRiskEngine
summary: Disable the Risk Engine
requestBody:
content:
@@ -28,7 +30,10 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/RiskEngineDisableResponse'
+ type: object
+ properties:
+ success:
+ type: boolean
'400':
description: Task manager is unavailable
content:
@@ -44,11 +49,6 @@ paths:
components:
schemas:
- RiskEngineDisableResponse:
- type: object
- properties:
- success:
- type: boolean
RiskEngineDisableErrorResponse:
type: object
required:
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_enable_route.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_enable_route.gen.ts
index cee1121b778ae..7bdbfd17449db 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_enable_route.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_enable_route.gen.ts
@@ -16,13 +16,13 @@
import { z } from 'zod';
-export type RiskEngineEnableResponse = z.infer;
-export const RiskEngineEnableResponse = z.object({
- success: z.boolean().optional(),
-});
-
-export type RiskEngineEnableErrorResponse = z.infer;
-export const RiskEngineEnableErrorResponse = z.object({
+export type EnableRiskEngineErrorResponse = z.infer;
+export const EnableRiskEngineErrorResponse = z.object({
message: z.string(),
full_error: z.string(),
});
+
+export type EnableRiskEngineResponse = z.infer;
+export const EnableRiskEngineResponse = z.object({
+ success: z.boolean().optional(),
+});
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_enable_route.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_enable_route.schema.yaml
index 5cfd5ffdd4fdf..6b2656bbb21b0 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_enable_route.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_enable_route.schema.yaml
@@ -18,6 +18,8 @@ paths:
post:
x-labels: [ess, serverless]
x-internal: true
+ x-codegen-enabled: true
+ operationId: EnableRiskEngine
summary: Enable the Risk Engine
requestBody:
content:
@@ -28,7 +30,10 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/RiskEngineEnableResponse'
+ type: object
+ properties:
+ success:
+ type: boolean
'400':
description: Task manager is unavailable
content:
@@ -40,16 +45,11 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/RiskEngineEnableErrorResponse'
+ $ref: '#/components/schemas/EnableRiskEngineErrorResponse'
components:
schemas:
- RiskEngineEnableResponse:
- type: object
- properties:
- success:
- type: boolean
- RiskEngineEnableErrorResponse:
+ EnableRiskEngineErrorResponse:
type: object
required:
- message
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_init_route.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_init_route.gen.ts
index d973a435b9aec..f9d79cd8f96a6 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_init_route.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_init_route.gen.ts
@@ -16,8 +16,8 @@
import { z } from 'zod';
-export type RiskEngineInitResult = z.infer;
-export const RiskEngineInitResult = z.object({
+export type InitRiskEngineResult = z.infer;
+export const InitRiskEngineResult = z.object({
risk_engine_enabled: z.boolean(),
risk_engine_resources_installed: z.boolean(),
risk_engine_configuration_created: z.boolean(),
@@ -25,13 +25,13 @@ export const RiskEngineInitResult = z.object({
errors: z.array(z.string()),
});
-export type RiskEngineInitResponse = z.infer;
-export const RiskEngineInitResponse = z.object({
- result: RiskEngineInitResult,
-});
-
-export type RiskEngineInitErrorResponse = z.infer;
-export const RiskEngineInitErrorResponse = z.object({
+export type InitRiskEngineErrorResponse = z.infer;
+export const InitRiskEngineErrorResponse = z.object({
message: z.string(),
full_error: z.string(),
});
+
+export type InitRiskEngineResponse = z.infer;
+export const InitRiskEngineResponse = z.object({
+ result: InitRiskEngineResult,
+});
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_init_route.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_init_route.schema.yaml
index 498ac266a9aa0..d1d35f4a720c6 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_init_route.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_init_route.schema.yaml
@@ -16,6 +16,8 @@ paths:
post:
x-labels: [ess, serverless]
x-internal: true
+ x-codegen-enabled: true
+ operationId: InitRiskEngine
summary: Initialize the Risk Engine
description: Initializes the Risk Engine by creating the necessary indices and mappings, removing old transforms, and starting the new risk engine
responses:
@@ -24,7 +26,12 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/RiskEngineInitResponse'
+ type: object
+ required:
+ - result
+ properties:
+ result:
+ $ref: '#/components/schemas/InitRiskEngineResult'
'400':
description: Task manager is unavailable
content:
@@ -36,11 +43,11 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/RiskEngineInitErrorResponse'
+ $ref: '#/components/schemas/InitRiskEngineErrorResponse'
components:
schemas:
- RiskEngineInitResult:
+ InitRiskEngineResult:
type: object
required:
- risk_engine_enabled
@@ -62,15 +69,7 @@ components:
items:
type: string
- RiskEngineInitResponse:
- type: object
- required:
- - result
- properties:
- result:
- $ref: '#/components/schemas/RiskEngineInitResult'
-
- RiskEngineInitErrorResponse:
+ InitRiskEngineErrorResponse:
type: object
required:
- message
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_settings_route.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_settings_route.gen.ts
index c8d10bd87d75e..e01edb31397a6 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_settings_route.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_settings_route.gen.ts
@@ -18,7 +18,7 @@ import { z } from 'zod';
import { DateRange } from '../common/common.gen';
-export type RiskEngineSettingsResponse = z.infer;
-export const RiskEngineSettingsResponse = z.object({
+export type ReadRiskEngineSettingsResponse = z.infer;
+export const ReadRiskEngineSettingsResponse = z.object({
range: DateRange.optional(),
});
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_settings_route.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_settings_route.schema.yaml
index 3622a9ff7c62b..a5cc6d6b44008 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_settings_route.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_settings_route.schema.yaml
@@ -16,7 +16,8 @@ paths:
get:
x-labels: [ess, serverless]
x-internal: true
- operationId: RiskEngineSettingsGet
+ x-codegen-enabled: true
+ operationId: ReadRiskEngineSettings
summary: Get the settings of the Risk Engine
responses:
'200':
@@ -24,12 +25,7 @@ paths:
content:
application/json:
schema:
- $ref: '#/components/schemas/RiskEngineSettingsResponse'
-
-components:
- schemas:
- RiskEngineSettingsResponse:
- type: object
- properties:
- range:
- $ref: '../common/common.schema.yaml#/components/schemas/DateRange'
+ type: object
+ properties:
+ range:
+ $ref: '../common/common.schema.yaml#/components/schemas/DateRange'
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_status_route.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_status_route.gen.ts
index 6a6e15d9c71a3..0d3fd0b9f0dd4 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_status_route.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_status_route.gen.ts
@@ -30,3 +30,6 @@ export const RiskEngineStatusResponse = z.object({
*/
is_max_amount_of_risk_engines_reached: z.boolean(),
});
+
+export type GetRiskEngineStatusResponse = z.infer;
+export const GetRiskEngineStatusResponse = RiskEngineStatusResponse;
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_status_route.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_status_route.schema.yaml
index 3f1cc33e94288..57f46b99f3a77 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_status_route.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/engine_status_route.schema.yaml
@@ -16,6 +16,8 @@ paths:
get:
x-labels: [ess, serverless]
x-internal: true
+ x-codegen-enabled: true
+ operationId: GetRiskEngineStatus
summary: Get the status of the Risk Engine
description: Returns the status of both the legacy transform-based risk engine, as well as the new risk engine
responses:
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.gen.ts
index c9b6c8cc47aa3..ebefbd772ed96 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.gen.ts
@@ -41,3 +41,29 @@ export const RiskScoresEntityCalculationResponse = z.object({
success: z.boolean(),
score: EntityRiskScoreRecord.optional(),
});
+
+export type DeprecatedTriggerRiskScoreCalculationRequestBody = z.infer<
+ typeof DeprecatedTriggerRiskScoreCalculationRequestBody
+>;
+export const DeprecatedTriggerRiskScoreCalculationRequestBody = RiskScoresEntityCalculationRequest;
+export type DeprecatedTriggerRiskScoreCalculationRequestBodyInput = z.input<
+ typeof DeprecatedTriggerRiskScoreCalculationRequestBody
+>;
+
+export type DeprecatedTriggerRiskScoreCalculationResponse = z.infer<
+ typeof DeprecatedTriggerRiskScoreCalculationResponse
+>;
+export const DeprecatedTriggerRiskScoreCalculationResponse = RiskScoresEntityCalculationResponse;
+
+export type TriggerRiskScoreCalculationRequestBody = z.infer<
+ typeof TriggerRiskScoreCalculationRequestBody
+>;
+export const TriggerRiskScoreCalculationRequestBody = RiskScoresEntityCalculationRequest;
+export type TriggerRiskScoreCalculationRequestBodyInput = z.input<
+ typeof TriggerRiskScoreCalculationRequestBody
+>;
+
+export type TriggerRiskScoreCalculationResponse = z.infer<
+ typeof TriggerRiskScoreCalculationResponse
+>;
+export const TriggerRiskScoreCalculationResponse = RiskScoresEntityCalculationResponse;
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.schema.yaml
index bb94305254885..69be93f7ceb49 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/entity_calculation_route.schema.yaml
@@ -19,8 +19,11 @@ paths:
post:
x-labels: [ess, serverless]
x-internal: true
+ x-codegen-enabled: true
+ operationId: DeprecatedTriggerRiskScoreCalculation
summary: Deprecated Trigger calculation of Risk Scores for an entity. Moved to /internal/risk_score/calculation/entity
description: Calculates and persists Risk Scores for an entity, returning the calculated risk score.
+ deprecated: true
requestBody:
description: The entity type and identifier
content:
@@ -41,6 +44,8 @@ paths:
/internal/risk_score/calculation/entity:
post:
x-labels: [ess, serverless]
+ x-codegen-enabled: true
+ operationId: TriggerRiskScoreCalculation
summary: Trigger calculation of Risk Scores for an entity
description: Calculates and persists Risk Scores for an entity, returning the calculated risk score.
requestBody:
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/preview_route.gen.ts b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/preview_route.gen.ts
index fe0b90e5a2e7a..13515d239c81c 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/preview_route.gen.ts
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/preview_route.gen.ts
@@ -83,3 +83,10 @@ export const RiskScoresPreviewResponse = z.object({
user: z.array(EntityRiskScoreRecord).optional(),
}),
});
+
+export type PreviewRiskScoreRequestBody = z.infer;
+export const PreviewRiskScoreRequestBody = RiskScoresPreviewRequest;
+export type PreviewRiskScoreRequestBodyInput = z.input;
+
+export type PreviewRiskScoreResponse = z.infer;
+export const PreviewRiskScoreResponse = RiskScoresPreviewResponse;
diff --git a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/preview_route.schema.yaml b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/preview_route.schema.yaml
index a2ce9bcafd697..424ca98436768 100644
--- a/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/preview_route.schema.yaml
+++ b/x-pack/plugins/security_solution/common/api/entity_analytics/risk_engine/preview_route.schema.yaml
@@ -16,6 +16,8 @@ paths:
post:
x-labels: [ess, serverless]
x-internal: true
+ x-codegen-enabled: true
+ operationId: PreviewRiskScore
summary: Preview the calculation of Risk Scores
description: Calculates and returns a list of Risk Scores, sorted by identifier_type and risk score.
requestBody:
diff --git a/x-pack/plugins/security_solution/common/api/timeline/model/api.ts b/x-pack/plugins/security_solution/common/api/timeline/model/api.ts
index 3e69bd14b646c..10b12aee32f2f 100644
--- a/x-pack/plugins/security_solution/common/api/timeline/model/api.ts
+++ b/x-pack/plugins/security_solution/common/api/timeline/model/api.ts
@@ -15,12 +15,31 @@ import { Direction } from '../../../search_strategy';
import type { PinnedEvent } from '../pinned_events/pinned_events_route';
import { PinnedEventRuntimeType } from '../pinned_events/pinned_events_route';
// TODO https://github.com/elastic/security-team/issues/7491
-// eslint-disable-next-line no-restricted-imports
-import {
- SavedObjectResolveAliasPurpose,
- SavedObjectResolveAliasTargetId,
- SavedObjectResolveOutcome,
-} from '../../detection_engine/model/rule_schema_legacy';
+
+/**
+ * Outcome is a property of the saved object resolve api
+ * will tell us info about the rule after 8.0 migrations
+ */
+export type SavedObjectResolveOutcome = runtimeTypes.TypeOf;
+export const SavedObjectResolveOutcome = runtimeTypes.union([
+ runtimeTypes.literal('exactMatch'),
+ runtimeTypes.literal('aliasMatch'),
+ runtimeTypes.literal('conflict'),
+]);
+
+export type SavedObjectResolveAliasTargetId = runtimeTypes.TypeOf<
+ typeof SavedObjectResolveAliasTargetId
+>;
+export const SavedObjectResolveAliasTargetId = runtimeTypes.string;
+
+export type SavedObjectResolveAliasPurpose = runtimeTypes.TypeOf<
+ typeof SavedObjectResolveAliasPurpose
+>;
+export const SavedObjectResolveAliasPurpose = runtimeTypes.union([
+ runtimeTypes.literal('savedObjectConversion'),
+ runtimeTypes.literal('savedObjectImport'),
+]);
+
import { ErrorSchema } from './error_schema';
export const BareNoteSchema = runtimeTypes.intersection([
diff --git a/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml b/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml
index 6cb21c69c0492..4fd2ec1aed3b6 100644
--- a/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml
+++ b/x-pack/plugins/security_solution/docs/openapi/ess/security_solution_detections_api_2023_10_31.bundled.schema.yaml
@@ -91,6 +91,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/SiemErrorResponse'
+ description: Not found
'500':
content:
application/json:
@@ -131,6 +132,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/SiemErrorResponse'
+ description: Not found
'500':
content:
application/json:
diff --git a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.ts b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.ts
index e56c10d589f5f..a483a5c465b3f 100644
--- a/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.ts
+++ b/x-pack/plugins/security_solution/public/common/hooks/endpoint/use_alert_response_actions_support.ts
@@ -9,6 +9,7 @@ import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
import { useMemo } from 'react';
import { find, some } from 'lodash/fp';
import { i18n } from '@kbn/i18n';
+import { getHostPlatform } from '../../lib/endpoint/utils/get_host_platform';
import { getAlertDetailsFieldValue } from '../../lib/endpoint/utils/get_event_details_field_values';
import { isAgentTypeAndActionSupported } from '../../lib/endpoint';
import type {
@@ -176,16 +177,8 @@ export const useAlertResponseActionsSupport = (
}, [eventData]);
const platform = useMemo(() => {
- // TODO:TC I couldn't find host.os.family in the example data, thus using host.os.type and host.os.platform which are present one at a time in different type of events
- if (agentType === 'crowdstrike') {
- return (
- getAlertDetailsFieldValue({ category: 'host', field: 'host.os.type' }, eventData) ||
- getAlertDetailsFieldValue({ category: 'host', field: 'host.os.platform' }, eventData)
- );
- }
-
- return getAlertDetailsFieldValue({ category: 'host', field: 'host.os.type' }, eventData);
- }, [agentType, eventData]);
+ return getHostPlatform(eventData ?? []);
+ }, [eventData]);
const unsupportedReason = useMemo(() => {
if (!doesHostSupportResponseActions) {
diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_host_platform.test.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_host_platform.test.ts
new file mode 100644
index 0000000000000..61cc2053eb8fc
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_host_platform.test.ts
@@ -0,0 +1,52 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { set } from 'lodash';
+import { getHostPlatform } from './get_host_platform';
+import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
+
+describe('getHostPlatform() util', () => {
+ const buildEcsData = (data: Record) => {
+ const ecsData = {};
+
+ for (const [key, value] of Object.entries(data)) {
+ set(ecsData, `host.os.${key}`, value);
+ }
+
+ return ecsData;
+ };
+
+ const buildEventDetails = (data: Record) => {
+ const eventDetails: TimelineEventsDetailsItem[] = [];
+
+ for (const [key, value] of Object.entries(data)) {
+ eventDetails.push({
+ category: 'host',
+ field: `host.os.${key}`,
+ values: [value],
+ originalValue: value,
+ isObjectArray: false,
+ });
+ }
+
+ return eventDetails;
+ };
+
+ it.each`
+ title | setupData | expectedResult
+ ${'ECS data with host.os.platform info'} | ${buildEcsData({ platform: 'windows' })} | ${'windows'}
+ ${'ECS data with host.os.type info'} | ${buildEcsData({ type: 'Linux' })} | ${'linux'}
+ ${'ECS data with host.os.name info'} | ${buildEcsData({ name: 'MACOS' })} | ${'macos'}
+ ${'ECS data with all os info'} | ${buildEcsData({ platform: 'macos', type: 'windows', name: 'linux' })} | ${'macos'}
+ ${'Event Details data with host.os.platform info'} | ${buildEventDetails({ platform: 'windows' })} | ${'windows'}
+ ${'Event Details data with host.os.type info'} | ${buildEventDetails({ type: 'Linux' })} | ${'linux'}
+ ${'Event Details data with host.os.name info'} | ${buildEventDetails({ name: 'MACOS' })} | ${'macos'}
+ ${'Event Details data with all os info'} | ${buildEventDetails({ platform: 'macos', type: 'windows', name: 'linux' })} | ${'macos'}
+ `(`should handle $title`, ({ setupData, expectedResult }) => {
+ expect(getHostPlatform(setupData)).toEqual(expectedResult);
+ });
+});
diff --git a/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_host_platform.ts b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_host_platform.ts
new file mode 100644
index 0000000000000..52df785cabff0
--- /dev/null
+++ b/x-pack/plugins/security_solution/public/common/lib/endpoint/utils/get_host_platform.ts
@@ -0,0 +1,39 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import type { Ecs } from '@elastic/ecs';
+import type { TimelineEventsDetailsItem } from '@kbn/timelines-plugin/common';
+import type { MaybeImmutable } from '../../../../../common/endpoint/types';
+import { getAlertDetailsFieldValue } from './get_event_details_field_values';
+import type { Platform } from '../../../../management/components/endpoint_responder/components/header_info/platforms';
+
+type EcsHostData = MaybeImmutable>;
+
+const isTimelineEventDetailsItems = (
+ data: EcsHostData | TimelineEventsDetailsItem[]
+): data is TimelineEventsDetailsItem[] => {
+ return Array.isArray(data);
+};
+
+/**
+ * Retrieve a host's platform type from either ECS data or Event Details list of items
+ * @param data
+ */
+export const getHostPlatform = (data: EcsHostData | TimelineEventsDetailsItem[]): Platform => {
+ let platform = '';
+
+ if (isTimelineEventDetailsItems(data)) {
+ platform = (getAlertDetailsFieldValue({ category: 'host', field: 'host.os.platform' }, data) ||
+ getAlertDetailsFieldValue({ category: 'host', field: 'host.os.type' }, data) ||
+ getAlertDetailsFieldValue({ category: 'host', field: 'host.os.name' }, data)) as Platform;
+ } else {
+ platform =
+ ((data.host?.os?.platform || data.host?.os?.type || data.host?.os?.name) as Platform) || '';
+ }
+
+ return platform.toLowerCase() as Platform;
+};
diff --git a/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts b/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts
index aa3b432533027..500c327d86b0c 100644
--- a/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts
+++ b/x-pack/plugins/security_solution/public/entity_analytics/api/api.ts
@@ -6,10 +6,11 @@
*/
import { useMemo } from 'react';
-import type { RiskEngineDisableResponse } from '../../../common/api/entity_analytics/risk_engine/engine_disable_route.gen';
+import type { UploadAssetCriticalityRecordsResponse } from '../../../common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen';
+import type { DisableRiskEngineResponse } from '../../../common/api/entity_analytics/risk_engine/engine_disable_route.gen';
import type { RiskEngineStatusResponse } from '../../../common/api/entity_analytics/risk_engine/engine_status_route.gen';
-import type { RiskEngineInitResponse } from '../../../common/api/entity_analytics/risk_engine/engine_init_route.gen';
-import type { RiskEngineEnableResponse } from '../../../common/api/entity_analytics/risk_engine/engine_enable_route.gen';
+import type { InitRiskEngineResponse } from '../../../common/api/entity_analytics/risk_engine/engine_init_route.gen';
+import type { EnableRiskEngineResponse } from '../../../common/api/entity_analytics/risk_engine/engine_enable_route.gen';
import type {
RiskScoresPreviewRequest,
RiskScoresPreviewResponse,
@@ -18,7 +19,6 @@ import type {
RiskScoresEntityCalculationRequest,
RiskScoresEntityCalculationResponse,
} from '../../../common/api/entity_analytics/risk_engine/entity_calculation_route.gen';
-import type { AssetCriticalityBulkUploadResponse } from '../../../common/entity_analytics/asset_criticality/types';
import type {
AssetCriticalityRecord,
EntityAnalyticsPrivileges,
@@ -39,9 +39,9 @@ import {
RISK_SCORE_ENTITY_CALCULATION_URL,
API_VERSIONS,
} from '../../../common/constants';
-import type { RiskEngineSettingsResponse } from '../../../common/api/entity_analytics/risk_engine';
import type { SnakeToCamelCase } from '../common/utils';
import { useKibana } from '../../common/lib/kibana/kibana_react';
+import type { ReadRiskEngineSettingsResponse } from '../../../common/api/entity_analytics/risk_engine';
export interface DeleteAssetCriticalityResponse {
deleted: true;
@@ -81,7 +81,7 @@ export const useEntityAnalyticsRoutes = () => {
* Init risk score engine
*/
const initRiskEngine = () =>
- http.fetch(RISK_ENGINE_INIT_URL, {
+ http.fetch(RISK_ENGINE_INIT_URL, {
version: '1',
method: 'POST',
});
@@ -90,7 +90,7 @@ export const useEntityAnalyticsRoutes = () => {
* Enable risk score engine
*/
const enableRiskEngine = () =>
- http.fetch(RISK_ENGINE_ENABLE_URL, {
+ http.fetch(RISK_ENGINE_ENABLE_URL, {
version: '1',
method: 'POST',
});
@@ -99,7 +99,7 @@ export const useEntityAnalyticsRoutes = () => {
* Disable risk score engine
*/
const disableRiskEngine = () =>
- http.fetch(RISK_ENGINE_DISABLE_URL, {
+ http.fetch(RISK_ENGINE_DISABLE_URL, {
version: '1',
method: 'POST',
});
@@ -181,12 +181,12 @@ export const useEntityAnalyticsRoutes = () => {
const uploadAssetCriticalityFile = async (
fileContent: string,
fileName: string
- ): Promise => {
+ ): Promise => {
const file = new File([new Blob([fileContent])], fileName, { type: 'text/csv' });
const body = new FormData();
body.append('file', file);
- return http.fetch(
+ return http.fetch(
ASSET_CRITICALITY_PUBLIC_CSV_UPLOAD_URL,
{
version: API_VERSIONS.public.v1,
@@ -224,7 +224,7 @@ export const useEntityAnalyticsRoutes = () => {
* Fetches risk engine settings
*/
const fetchRiskEngineSettings = () =>
- http.fetch(RISK_ENGINE_SETTINGS_URL, {
+ http.fetch(RISK_ENGINE_SETTINGS_URL, {
version: '1',
method: 'GET',
});
diff --git a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_disable_risk_engine_mutation.ts b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_disable_risk_engine_mutation.ts
index e19cf94fc379f..fb8a0bbb12972 100644
--- a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_disable_risk_engine_mutation.ts
+++ b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_disable_risk_engine_mutation.ts
@@ -9,7 +9,7 @@ import { useMutation } from '@tanstack/react-query';
import type { TaskManagerUnavailableResponse } from '../../../../common/api/entity_analytics/common';
import type {
RiskEngineDisableErrorResponse,
- RiskEngineDisableResponse,
+ DisableRiskEngineResponse,
} from '../../../../common/api/entity_analytics/risk_engine/engine_disable_route.gen';
import { useEntityAnalyticsRoutes } from '../api';
import { useInvalidateRiskEngineStatusQuery } from './use_risk_engine_status';
@@ -21,7 +21,7 @@ export const useDisableRiskEngineMutation = (options?: UseMutationOptions<{}>) =
const { disableRiskEngine } = useEntityAnalyticsRoutes();
return useMutation<
- RiskEngineDisableResponse,
+ DisableRiskEngineResponse,
{ body: RiskEngineDisableErrorResponse | TaskManagerUnavailableResponse }
>(() => disableRiskEngine(), {
...options,
diff --git a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_enable_risk_engine_mutation.ts b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_enable_risk_engine_mutation.ts
index 658c4a5cdb185..cd5083d13892e 100644
--- a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_enable_risk_engine_mutation.ts
+++ b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_enable_risk_engine_mutation.ts
@@ -8,8 +8,8 @@ import type { UseMutationOptions } from '@tanstack/react-query';
import { useMutation } from '@tanstack/react-query';
import type { TaskManagerUnavailableResponse } from '../../../../common/api/entity_analytics/common';
import type {
- RiskEngineEnableErrorResponse,
- RiskEngineEnableResponse,
+ EnableRiskEngineErrorResponse,
+ EnableRiskEngineResponse,
} from '../../../../common/api/entity_analytics/risk_engine/engine_enable_route.gen';
import { useEntityAnalyticsRoutes } from '../api';
import { useInvalidateRiskEngineStatusQuery } from './use_risk_engine_status';
@@ -19,8 +19,8 @@ export const useEnableRiskEngineMutation = (options?: UseMutationOptions<{}>) =>
const invalidateRiskEngineStatusQuery = useInvalidateRiskEngineStatusQuery();
const { enableRiskEngine } = useEntityAnalyticsRoutes();
return useMutation<
- RiskEngineEnableResponse,
- { body: RiskEngineEnableErrorResponse | TaskManagerUnavailableResponse }
+ EnableRiskEngineResponse,
+ { body: EnableRiskEngineErrorResponse | TaskManagerUnavailableResponse }
>(enableRiskEngine, {
...options,
mutationKey: ENABLE_RISK_ENGINE_MUTATION_KEY,
diff --git a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_init_risk_engine_mutation.ts b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_init_risk_engine_mutation.ts
index 67d94257e9165..d774853c7d026 100644
--- a/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_init_risk_engine_mutation.ts
+++ b/x-pack/plugins/security_solution/public/entity_analytics/api/hooks/use_init_risk_engine_mutation.ts
@@ -6,11 +6,11 @@
*/
import type { UseMutationOptions } from '@tanstack/react-query';
import { useMutation } from '@tanstack/react-query';
-import type { TaskManagerUnavailableResponse } from '../../../../common/api/entity_analytics/common';
import type {
- RiskEngineInitErrorResponse,
- RiskEngineInitResponse,
+ InitRiskEngineErrorResponse,
+ InitRiskEngineResponse,
} from '../../../../common/api/entity_analytics/risk_engine/engine_init_route.gen';
+import type { TaskManagerUnavailableResponse } from '../../../../common/api/entity_analytics/common';
import { useEntityAnalyticsRoutes } from '../api';
import { useInvalidateRiskEngineStatusQuery } from './use_risk_engine_status';
@@ -21,8 +21,8 @@ export const useInitRiskEngineMutation = (options?: UseMutationOptions<{}>) => {
const { initRiskEngine } = useEntityAnalyticsRoutes();
return useMutation<
- RiskEngineInitResponse,
- { body: RiskEngineInitErrorResponse | TaskManagerUnavailableResponse }
+ InitRiskEngineResponse,
+ { body: InitRiskEngineErrorResponse | TaskManagerUnavailableResponse }
>(() => initRiskEngine(), {
...options,
mutationKey: INIT_RISK_ENGINE_STATUS_KEY,
diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/result_step.tsx b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/result_step.tsx
index 1652c85eace1f..c3be648103d7f 100644
--- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/result_step.tsx
+++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/components/result_step.tsx
@@ -18,11 +18,11 @@ import React from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { i18n } from '@kbn/i18n';
import { css } from '@emotion/react';
-import type { AssetCriticalityBulkUploadResponse } from '../../../../../common/entity_analytics/asset_criticality/types';
+import type { BulkUpsertAssetCriticalityRecordsResponse } from '../../../../../common/entity_analytics/asset_criticality/types';
import { buildAnnotationsFromError } from '../helpers';
export const AssetCriticalityResultStep: React.FC<{
- result?: AssetCriticalityBulkUploadResponse;
+ result?: BulkUpsertAssetCriticalityRecordsResponse;
validLinesAsText: string;
errorMessage?: string;
onReturn: () => void;
diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.test.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.test.ts
index 60b6191a777d6..3fa2eb89e5d65 100644
--- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.test.ts
+++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.test.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import type { AssetCriticalityBulkUploadResponse } from '../../../../common/api/entity_analytics';
+import type { UploadAssetCriticalityRecordsResponse } from '../../../../common/api/entity_analytics';
import type { ReducerAction, ReducerState, ValidationStepState } from './reducer';
import { reducer } from './reducer';
import { FileUploaderSteps } from './types';
@@ -43,7 +43,7 @@ describe('reducer', () => {
});
it('should handle "fileUploaded" action with response', () => {
- const response: AssetCriticalityBulkUploadResponse = {
+ const response: UploadAssetCriticalityRecordsResponse = {
errors: [],
stats: {
total: 10,
diff --git a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.ts b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.ts
index e7f233015434f..eb0153d261871 100644
--- a/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.ts
+++ b/x-pack/plugins/security_solution/public/entity_analytics/components/asset_criticality_file_uploader/reducer.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
-import type { AssetCriticalityBulkUploadResponse } from '../../../../common/entity_analytics/asset_criticality/types';
+import type { UploadAssetCriticalityRecordsResponse } from '../../../../common/api/entity_analytics';
import { FileUploaderSteps } from './types';
import type { ValidatedFile } from './types';
import { isFilePickerStep, isValidationStep } from './helpers';
@@ -26,7 +26,7 @@ export interface ValidationStepState {
export interface ResultStepState {
step: FileUploaderSteps.RESULT;
- fileUploadResponse?: AssetCriticalityBulkUploadResponse;
+ fileUploadResponse?: UploadAssetCriticalityRecordsResponse;
fileUploadError?: string;
validLinesAsText: string;
}
@@ -46,7 +46,7 @@ export type ReducerAction =
| { type: 'uploadingFile' }
| {
type: 'fileUploaded';
- payload: { response?: AssetCriticalityBulkUploadResponse; errorMessage?: string };
+ payload: { response?: UploadAssetCriticalityRecordsResponse; errorMessage?: string };
};
export const INITIAL_STATE: FilePickerState = {
diff --git a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/endpoint/header_endpoint_info.tsx b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/endpoint/header_endpoint_info.tsx
index f302a31c5f48e..0cd96b4f3acf0 100644
--- a/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/endpoint/header_endpoint_info.tsx
+++ b/x-pack/plugins/security_solution/public/management/components/endpoint_responder/components/header_info/endpoint/header_endpoint_info.tsx
@@ -7,6 +7,7 @@
import React, { memo } from 'react';
import { EuiSkeletonText } from '@elastic/eui';
+import { getHostPlatform } from '../../../../../../common/lib/endpoint/utils/get_host_platform';
import { AgentStatus } from '../../../../../../common/components/endpoint/agents/agent_status';
import { HeaderAgentInfo } from '../header_agent_info';
import { useGetEndpointDetails } from '../../../../../hooks';
@@ -31,7 +32,7 @@ export const HeaderEndpointInfo = memo(({ endpointId })
return (
{
const HEARTBEAT_COUNT = 2001;
diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx
index abda617e2a779..9773e8f7eafb6 100644
--- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx
+++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/view/hooks/use_endpoint_action_items.tsx
@@ -8,7 +8,6 @@
import React, { useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { pagePathGetters } from '@kbn/fleet-plugin/public';
-import type { Platform } from '../../../../components/endpoint_responder/components/header_info/platforms';
import type { EndpointCapabilities } from '../../../../../../common/endpoint/service/response_actions/constants';
import { useUserPrivileges } from '../../../../../common/components/user_privileges';
import { useWithShowResponder } from '../../../../hooks';
@@ -20,6 +19,7 @@ import { agentPolicies, uiQueryParams } from '../../store/selectors';
import { useAppUrl } from '../../../../../common/lib/kibana/hooks';
import type { ContextMenuItemNavByRouterProps } from '../../../../components/context_menu_with_router_support/context_menu_item_nav_by_router';
import { isEndpointHostIsolated } from '../../../../../common/utils/validators';
+import { getHostPlatform } from '../../../../../common/lib/endpoint/utils/get_host_platform';
interface Options {
isEndpointList: boolean;
@@ -131,7 +131,7 @@ export const useEndpointActionItems = (
capabilities:
(endpointMetadata.Endpoint.capabilities as EndpointCapabilities[]) ?? [],
hostName: endpointMetadata.host.name,
- platform: endpointMetadata.host.os.name.toLowerCase() as Platform,
+ platform: getHostPlatform(endpointMetadata),
});
},
children: (
diff --git a/x-pack/plugins/security_solution/scripts/openapi/generate.js b/x-pack/plugins/security_solution/scripts/openapi/generate.js
index 38eb0fe06f95a..adfe11192ae49 100644
--- a/x-pack/plugins/security_solution/scripts/openapi/generate.js
+++ b/x-pack/plugins/security_solution/scripts/openapi/generate.js
@@ -18,7 +18,6 @@ const SECURITY_SOLUTION_ROOT = resolve(__dirname, '../..');
rootDir: SECURITY_SOLUTION_ROOT,
sourceGlob: './common/**/*.schema.yaml',
templateName: 'zod_operation_schema',
- skipLinting: true,
});
await generate({
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.test.ts
index 6490c1f0f18ec..2cc6d8efd199e 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.test.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.test.ts
@@ -80,7 +80,12 @@ describe('Response Actions file download API', () => {
it('should error if user has no authz to api', async () => {
(
(await httpHandlerContextMock.securitySolution).getEndpointAuthz as jest.Mock
- ).mockResolvedValue(getEndpointAuthzInitialStateMock({ canWriteFileOperations: false }));
+ ).mockResolvedValue(
+ getEndpointAuthzInitialStateMock({
+ canWriteFileOperations: false,
+ canWriteExecuteOperations: false,
+ })
+ );
await apiTestSetup
.getRegisteredVersionedRoute('get', ACTION_AGENT_FILE_DOWNLOAD_ROUTE, '2023-10-31')
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts
index 0037d5dded81f..7095b7d87a50c 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_download_handler.ts
@@ -47,7 +47,7 @@ export const registerActionFileDownloadRoutes = (
},
},
withEndpointAuthz(
- { all: ['canWriteFileOperations'] },
+ { any: ['canWriteFileOperations', 'canWriteExecuteOperations'] },
logger,
getActionFileDownloadRouteHandler(endpointContext)
)
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.test.ts
index e6554ee14ad6d..e9914dc4232d9 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.test.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.test.ts
@@ -69,7 +69,12 @@ describe('Response Action file info API', () => {
it('should error if user has no authz to api', async () => {
(
(await httpHandlerContextMock.securitySolution).getEndpointAuthz as jest.Mock
- ).mockResolvedValue(getEndpointAuthzInitialStateMock({ canWriteFileOperations: false }));
+ ).mockResolvedValue(
+ getEndpointAuthzInitialStateMock({
+ canWriteFileOperations: false,
+ canWriteExecuteOperations: false,
+ })
+ );
await apiTestSetup
.getRegisteredVersionedRoute('get', ACTION_AGENT_FILE_INFO_ROUTE, '2023-10-31')
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.ts
index abc576fe3c9d9..a84f3b3a8bf6f 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/file_info_handler.ts
@@ -83,7 +83,7 @@ export const registerActionFileInfoRoute = (
},
},
withEndpointAuthz(
- { all: ['canWriteFileOperations'] },
+ { any: ['canWriteFileOperations', 'canWriteExecuteOperations'] },
endpointContext.logFactory.get('actionFileInfo'),
getActionFileInfoRouteHandler(endpointContext)
)
diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/with_endpoint_authz.ts b/x-pack/plugins/security_solution/server/endpoint/routes/with_endpoint_authz.ts
index 8822db6c68367..a241148c7b714 100644
--- a/x-pack/plugins/security_solution/server/endpoint/routes/with_endpoint_authz.ts
+++ b/x-pack/plugins/security_solution/server/endpoint/routes/with_endpoint_authz.ts
@@ -6,6 +6,7 @@
*/
import type { RequestHandler, Logger } from '@kbn/core/server';
+import { stringify } from '../utils/stringify';
import type { EndpointAuthzKeyList } from '../../../common/endpoint/types/authz';
import type { SecuritySolutionRequestHandlerContext } from '../../types';
import { EndpointAuthorizationError } from '../errors';
@@ -39,6 +40,21 @@ export const withEndpointAuthz = (
const validateAll = needAll.length > 0;
const validateAny = needAny.length > 0;
const enforceAuthz = validateAll || validateAny;
+ const logAuthzFailure = (
+ user: string,
+ authzValidationResults: Record,
+ needed: string[]
+ ) => {
+ logger.debug(
+ `Unauthorized: user ${user} ${
+ needed === needAll ? 'needs ALL' : 'needs at least one'
+ } of the following privileges:\n${stringify(needed)}\nbut is missing: ${stringify(
+ Object.entries(authzValidationResults)
+ .filter(([_, value]) => !value)
+ .map(([key]) => key)
+ )}`
+ );
+ };
if (!enforceAuthz) {
logger.warn(`Authorization disabled for API route: ${new Error('').stack ?? '?'}`);
@@ -51,18 +67,37 @@ export const withEndpointAuthz = (
SecuritySolutionRequestHandlerContext
> = async (context, request, response) => {
if (enforceAuthz) {
+ const coreServices = await context.core;
const endpointAuthz = await (await context.securitySolution).getEndpointAuthz();
- const permissionChecker = (permission: EndpointAuthzKeyList[0]) => endpointAuthz[permission];
+ let authzValidationResults: Record = {};
+ const permissionChecker = (permission: EndpointAuthzKeyList[0]) => {
+ authzValidationResults[permission] = endpointAuthz[permission];
+ return endpointAuthz[permission];
+ };
// has `all`?
if (validateAll && !needAll.every(permissionChecker)) {
+ logAuthzFailure(
+ coreServices.security.authc.getCurrentUser()?.username ?? '',
+ authzValidationResults,
+ needAll
+ );
+
return response.forbidden({
body: new EndpointAuthorizationError({ need_all: [...needAll] }),
});
}
+ authzValidationResults = {};
+
// has `any`?
if (validateAny && !needAny.some(permissionChecker)) {
+ logAuthzFailure(
+ coreServices.security.authc.getCurrentUser()?.username ?? '',
+ authzValidationResults,
+ needAny
+ );
+
return response.forbidden({
body: new EndpointAuthorizationError({ need_any: [...needAny] }),
});
diff --git a/x-pack/plugins/security_solution/server/integration_tests/telemetry.test.ts b/x-pack/plugins/security_solution/server/integration_tests/telemetry.test.ts
index 7a38948c0c46d..46f85a01f4760 100644
--- a/x-pack/plugins/security_solution/server/integration_tests/telemetry.test.ts
+++ b/x-pack/plugins/security_solution/server/integration_tests/telemetry.test.ts
@@ -683,7 +683,8 @@ describe('telemetry tasks', () => {
});
});
- describe('telemetry-prebuilt-rule-alerts', () => {
+ // FLAKY: https://github.com/elastic/kibana/issues/188234
+ describe.skip('telemetry-prebuilt-rule-alerts', () => {
it('should execute when scheduled', async () => {
await mockAndSchedulePrebuiltRulesTask();
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts
index 819bf87165e12..687bf91655e2a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/__mocks__/utils.ts
@@ -47,6 +47,9 @@ export const getOutputRuleAlertForRest = (): RuleResponse => ({
from: 'now-6m',
id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd',
immutable: false,
+ rule_source: {
+ type: 'internal',
+ },
index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
interval: '5m',
risk_score: 50,
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/legacy_rules_notification_rule_type.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/legacy_rules_notification_rule_type.test.ts
index 767c01f02b187..4adf71d258e0a 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/legacy_rules_notification_rule_type.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_actions_legacy/logic/notifications/legacy_rules_notification_rule_type.test.ts
@@ -76,6 +76,9 @@ const reported = {
from: 'now-6m',
id: 'rule-id',
immutable: false,
+ rule_source: {
+ type: 'internal',
+ },
index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
investigation_fields: undefined,
language: 'kuery',
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/internal_rule_to_api_response.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/internal_rule_to_api_response.ts
index 452f59df8dcf9..349f54b1e3b3c 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/internal_rule_to_api_response.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/internal_rule_to_api_response.ts
@@ -17,6 +17,7 @@ import {
} from '../../../normalization/rule_actions';
import { typeSpecificCamelToSnake } from './type_specific_camel_to_snake';
import { commonParamsCamelToSnake } from './common_params_camel_to_snake';
+import { normalizeRuleParams } from './normalize_rule_params';
export const internalRuleToAPIResponse = (
rule: SanitizedRule | ResolvedSanitizedRule
@@ -31,6 +32,7 @@ export const internalRuleToAPIResponse = (
const alertActions = rule.actions.map(transformAlertToRuleAction);
const throttle = transformFromAlertThrottle(rule);
const actions = transformToActionFrequency(alertActions, throttle);
+ const normalizedRuleParams = normalizeRuleParams(rule.params);
return {
// saved object properties
@@ -49,7 +51,7 @@ export const internalRuleToAPIResponse = (
enabled: rule.enabled,
revision: rule.revision,
// Security solution shared rule params
- ...commonParamsCamelToSnake(rule.params),
+ ...commonParamsCamelToSnake(normalizedRuleParams),
// Type specific security solution rule params
...typeSpecificCamelToSnake(rule.params),
// Actions
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/normalize_rule_params.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/normalize_rule_params.test.ts
new file mode 100644
index 0000000000000..b8b5db137583b
--- /dev/null
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/normalize_rule_params.test.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+
+import { normalizeRuleSource } from './normalize_rule_params';
+import type { BaseRuleParams } from '../../../../rule_schema';
+
+describe('normalizeRuleSource', () => {
+ it('should return rule_source of type `internal` when immutable is false and ruleSource is undefined', () => {
+ const result = normalizeRuleSource({
+ immutable: false,
+ ruleSource: undefined,
+ });
+ expect(result).toEqual({
+ type: 'internal',
+ });
+ });
+
+ it('should return rule_source of type `external` and `isCustomized: false` when immutable is true and ruleSource is undefined', () => {
+ const result = normalizeRuleSource({
+ immutable: true,
+ ruleSource: undefined,
+ });
+ expect(result).toEqual({
+ type: 'external',
+ isCustomized: false,
+ });
+ });
+
+ it('should return existing value when ruleSource is present', () => {
+ const externalRuleSource: BaseRuleParams['ruleSource'] = {
+ type: 'external',
+ isCustomized: true,
+ };
+ const externalResult = normalizeRuleSource({ immutable: true, ruleSource: externalRuleSource });
+ expect(externalResult).toEqual({
+ type: externalRuleSource.type,
+ isCustomized: externalRuleSource.isCustomized,
+ });
+
+ const internalRuleSource: BaseRuleParams['ruleSource'] = {
+ type: 'internal',
+ };
+ const internalResult = normalizeRuleSource({
+ immutable: false,
+ ruleSource: internalRuleSource,
+ });
+ expect(internalResult).toEqual({
+ type: internalRuleSource.type,
+ });
+ });
+});
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/normalize_rule_params.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/normalize_rule_params.ts
new file mode 100644
index 0000000000000..eddd8b0434ba0
--- /dev/null
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/detection_rules_client/converters/normalize_rule_params.ts
@@ -0,0 +1,48 @@
+/*
+ * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
+ * or more contributor license agreements. Licensed under the Elastic License
+ * 2.0; you may not use this file except in compliance with the Elastic License
+ * 2.0.
+ */
+import type { BaseRuleParams, RuleSourceCamelCased } from '../../../../rule_schema';
+
+interface NormalizeRuleSourceParams {
+ immutable: BaseRuleParams['immutable'];
+ ruleSource: BaseRuleParams['ruleSource'];
+}
+
+/*
+ * Since there's no mechanism to migrate all rules at the same time,
+ * we cannot guarantee that the ruleSource params is present in all rules.
+ * This function will normalize the ruleSource param, creating it if does
+ * not exist in ES, based on the immutable param.
+ */
+export const normalizeRuleSource = ({
+ immutable,
+ ruleSource,
+}: NormalizeRuleSourceParams): RuleSourceCamelCased => {
+ if (!ruleSource) {
+ const normalizedRuleSource: RuleSourceCamelCased = immutable
+ ? {
+ type: 'external',
+ isCustomized: false,
+ }
+ : {
+ type: 'internal',
+ };
+
+ return normalizedRuleSource;
+ }
+ return ruleSource;
+};
+
+export const normalizeRuleParams = (params: BaseRuleParams) => {
+ return {
+ ...params,
+ // Fields to normalize
+ ruleSource: normalizeRuleSource({
+ immutable: params.immutable,
+ ruleSource: params.ruleSource,
+ }),
+ };
+};
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.test.ts
index 0ba0afbce715a..382df4bfa5ffc 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/logic/export/get_export_all.test.ts
@@ -100,6 +100,9 @@ describe('getExportAll', () => {
from: 'now-6m',
id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd',
immutable: false,
+ rule_source: {
+ type: 'internal',
+ },
index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
interval: '5m',
rule_id: 'rule-1',
@@ -280,6 +283,9 @@ describe('getExportAll', () => {
from: 'now-6m',
id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd',
immutable: false,
+ rule_source: {
+ type: 'internal',
+ },
index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
interval: '5m',
rule_id: 'rule-1',
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.test.ts
index f11e31691d25b..c9a5a93a4f1c3 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_management/utils/validate.test.ts
@@ -8,85 +8,15 @@
import { transformValidateBulkError } from './validate';
import type { BulkError } from '../../routes/utils';
import { getRuleMock } from '../../routes/__mocks__/request_responses';
-import { getListArrayMock } from '../../../../../common/detection_engine/schemas/types/lists.mock';
-import { getThreatMock } from '../../../../../common/detection_engine/schemas/types/threat.mock';
import { getQueryRuleParams } from '../../rule_schema/mocks';
-import type { RuleResponse } from '../../../../../common/api/detection_engine/model/rule_schema';
-
-export const ruleOutput = (): RuleResponse => ({
- actions: [],
- author: ['Elastic'],
- building_block_type: 'default',
- created_at: '2019-12-13T16:40:33.400Z',
- updated_at: '2019-12-13T16:40:33.400Z',
- created_by: 'elastic',
- description: 'Detecting root and admin users',
- enabled: true,
- false_positives: [],
- from: 'now-6m',
- id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd',
- immutable: false,
- interval: '5m',
- rule_id: 'rule-1',
- language: 'kuery',
- license: 'Elastic License',
- output_index: '.siem-signals',
- max_signals: 10000,
- risk_score: 50,
- risk_score_mapping: [],
- name: 'Detect Root/Admin Users',
- query: 'user.name: root or user.name: admin',
- references: ['http://example.com', 'https://example.com'],
- severity: 'high',
- severity_mapping: [],
- updated_by: 'elastic',
- tags: [],
- to: 'now',
- type: 'query',
- throttle: undefined,
- threat: getThreatMock(),
- version: 1,
- revision: 0,
- filters: [
- {
- query: {
- match_phrase: {
- 'host.name': 'some-host',
- },
- },
- },
- ],
- exceptions_list: getListArrayMock(),
- index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
- meta: {
- someMeta: 'someField',
- },
- note: '# Investigative notes',
- timeline_title: 'some-timeline-title',
- timeline_id: 'some-timeline-id',
- related_integrations: [],
- required_fields: [],
- response_actions: undefined,
- setup: '',
- outcome: undefined,
- alias_target_id: undefined,
- alias_purpose: undefined,
- rule_name_override: undefined,
- timestamp_override: undefined,
- timestamp_override_fallback_disabled: undefined,
- namespace: undefined,
- data_view_id: undefined,
- saved_id: undefined,
- alert_suppression: undefined,
- investigation_fields: undefined,
-});
+import { getOutputRuleAlertForRest } from '../../routes/__mocks__/utils';
describe('validate', () => {
describe('transformValidateBulkError', () => {
test('it should do a validation correctly of a rule id', () => {
const ruleAlert = getRuleMock(getQueryRuleParams());
const validatedOrError = transformValidateBulkError('rule-1', ruleAlert);
- expect(validatedOrError).toEqual(ruleOutput());
+ expect(validatedOrError).toEqual(getOutputRuleAlertForRest());
});
test('it should do an in-validation correctly of a rule id', () => {
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.mock.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.mock.ts
index 3a4fa1dadd778..8099d7a00049f 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.mock.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_schema/model/rule_schemas.mock.ts
@@ -32,6 +32,9 @@ export const getBaseRuleParams = (): BaseRuleParams => {
description: 'Detecting root and admin users',
falsePositives: [],
immutable: false,
+ ruleSource: {
+ type: 'internal',
+ },
from: 'now-6m',
to: 'now',
severity: 'high',
diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts
index ffb5f6ee45170..4aaa0189eefc4 100644
--- a/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts
+++ b/x-pack/plugins/security_solution/server/lib/detection_engine/rule_types/factories/utils/build_alert.test.ts
@@ -162,6 +162,9 @@ describe('buildAlert', () => {
},
],
immutable: false,
+ rule_source: {
+ type: 'internal',
+ },
type: 'query',
language: 'kuery',
index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
@@ -357,6 +360,9 @@ describe('buildAlert', () => {
},
],
immutable: false,
+ rule_source: {
+ type: 'internal',
+ },
type: 'query',
language: 'kuery',
index: ['auditbeat-*', 'filebeat-*', 'packetbeat-*', 'winlogbeat-*'],
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts
index ac22303c09af6..4770d051f2e99 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/asset_criticality_data_client.ts
@@ -11,7 +11,7 @@ import { mappingFromFieldMap } from '@kbn/alerting-plugin/common';
import type { AuditLogger } from '@kbn/security-plugin-types-server';
import { fromKueryExpression, toElasticsearchQuery } from '@kbn/es-query';
import type {
- AssetCriticalityBulkUploadResponse,
+ BulkUpsertAssetCriticalityRecordsResponse,
AssetCriticalityUpsert,
} from '../../../../common/entity_analytics/asset_criticality/types';
import type { AssetCriticalityRecord } from '../../../../common/api/entity_analytics';
@@ -211,9 +211,9 @@ export class AssetCriticalityDataClient {
recordsStream,
flushBytes,
retries,
- }: BulkUpsertFromStreamOptions): Promise => {
- const errors: AssetCriticalityBulkUploadResponse['errors'] = [];
- const stats: AssetCriticalityBulkUploadResponse['stats'] = {
+ }: BulkUpsertFromStreamOptions): Promise => {
+ const errors: BulkUpsertAssetCriticalityRecordsResponse['errors'] = [];
+ const stats: BulkUpsertAssetCriticalityRecordsResponse['stats'] = {
successful: 0,
failed: 0,
total: 0,
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/bulk_upload.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/bulk_upload.ts
index e1eb6872d3a33..822c8a644d9b3 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/bulk_upload.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/bulk_upload.ts
@@ -9,8 +9,8 @@ import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
import { Readable } from 'node:stream';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
-import type { AssetCriticalityBulkUploadResponse } from '../../../../../common/api/entity_analytics';
-import { AssetCriticalityBulkUploadRequest } from '../../../../../common/api/entity_analytics';
+import type { BulkUpsertAssetCriticalityRecordsResponse } from '../../../../../common/api/entity_analytics';
+import { BulkUpsertAssetCriticalityRecordsRequestBody } from '../../../../../common/api/entity_analytics';
import type { ConfigType } from '../../../../config';
import {
ASSET_CRITICALITY_PUBLIC_BULK_UPLOAD_URL,
@@ -42,7 +42,7 @@ export const assetCriticalityPublicBulkUploadRoute = (
version: API_VERSIONS.public.v1,
validate: {
request: {
- body: buildRouteValidationWithZod(AssetCriticalityBulkUploadRequest),
+ body: buildRouteValidationWithZod(BulkUpsertAssetCriticalityRecordsRequestBody),
},
},
},
@@ -90,7 +90,7 @@ export const assetCriticalityPublicBulkUploadRoute = (
() => `Asset criticality Bulk upload completed in ${tookMs}ms ${JSON.stringify(stats)}`
);
- const resBody: AssetCriticalityBulkUploadResponse = { errors, stats };
+ const resBody: BulkUpsertAssetCriticalityRecordsResponse = { errors, stats };
return response.ok({ body: resBody });
} catch (e) {
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts
index c7a0f07400cc8..b39013359eed4 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/delete.ts
@@ -8,6 +8,10 @@ import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/s
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
+import {
+ DeleteAssetCriticalityRecordRequestQuery,
+ InternalDeleteAssetCriticalityRecordRequestQuery,
+} from '../../../../../common/api/entity_analytics/asset_criticality/delete_asset_criticality.gen';
import type { SecuritySolutionRequestHandlerContext } from '../../../../types';
import {
ASSET_CRITICALITY_PUBLIC_URL,
@@ -16,7 +20,6 @@ import {
ENABLE_ASSET_CRITICALITY_SETTING,
API_VERSIONS,
} from '../../../../../common/constants';
-import { DeleteAssetCriticalityRecord } from '../../../../../common/api/entity_analytics/asset_criticality';
import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources';
import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setting_enabled';
import type { EntityAnalyticsRoutesDeps } from '../../types';
@@ -26,7 +29,7 @@ import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit';
type DeleteHandler = (
context: SecuritySolutionRequestHandlerContext,
request: {
- query: DeleteAssetCriticalityRecord;
+ query: DeleteAssetCriticalityRecordRequestQuery;
},
response: KibanaResponseFactory
) => Promise;
@@ -88,7 +91,7 @@ export const assetCriticalityInternalDeleteRoute = (
version: API_VERSIONS.internal.v1,
validate: {
request: {
- query: buildRouteValidationWithZod(DeleteAssetCriticalityRecord),
+ query: buildRouteValidationWithZod(InternalDeleteAssetCriticalityRecordRequestQuery),
},
},
},
@@ -113,7 +116,7 @@ export const assetCriticalityPublicDeleteRoute = (
version: API_VERSIONS.public.v1,
validate: {
request: {
- query: buildRouteValidationWithZod(DeleteAssetCriticalityRecord),
+ query: buildRouteValidationWithZod(DeleteAssetCriticalityRecordRequestQuery),
},
},
},
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts
index 07d0cb3098dbc..e1ab013a373b6 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/get.ts
@@ -8,6 +8,7 @@ import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/s
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
+import { GetAssetCriticalityRecordRequestQuery } from '../../../../../common/api/entity_analytics/asset_criticality/get_asset_criticality.gen';
import type { SecuritySolutionRequestHandlerContext } from '../../../../types';
import {
ASSET_CRITICALITY_INTERNAL_URL,
@@ -17,7 +18,6 @@ import {
API_VERSIONS,
} from '../../../../../common/constants';
import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources';
-import { AssetCriticalityRecordIdParts } from '../../../../../common/api/entity_analytics/asset_criticality';
import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setting_enabled';
import type { EntityAnalyticsRoutesDeps } from '../../types';
import { AssetCriticalityAuditActions } from '../audit';
@@ -25,7 +25,7 @@ import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit';
type GetHandler = (
context: SecuritySolutionRequestHandlerContext,
request: {
- query: AssetCriticalityRecordIdParts;
+ query: GetAssetCriticalityRecordRequestQuery;
},
response: KibanaResponseFactory
) => Promise;
@@ -86,7 +86,7 @@ export const assetCriticalityInternalGetRoute = (
version: API_VERSIONS.internal.v1,
validate: {
request: {
- query: buildRouteValidationWithZod(AssetCriticalityRecordIdParts),
+ query: buildRouteValidationWithZod(GetAssetCriticalityRecordRequestQuery),
},
},
},
@@ -111,7 +111,7 @@ export const assetCriticalityPublicGetRoute = (
version: API_VERSIONS.public.v1,
validate: {
request: {
- query: buildRouteValidationWithZod(AssetCriticalityRecordIdParts),
+ query: buildRouteValidationWithZod(GetAssetCriticalityRecordRequestQuery),
},
},
},
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/list.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/list.ts
index 66db32f2bdb17..711426e4df510 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/list.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/list.ts
@@ -15,8 +15,8 @@ import {
API_VERSIONS,
} from '../../../../../common/constants';
import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources';
-import type { AssetCriticalityListResponse } from '../../../../../common/api/entity_analytics/asset_criticality';
-import { ListAssetCriticalityQueryParams } from '../../../../../common/api/entity_analytics/asset_criticality';
+import type { FindAssetCriticalityRecordsResponse } from '../../../../../common/api/entity_analytics/asset_criticality';
+import { FindAssetCriticalityRecordsRequestQuery } from '../../../../../common/api/entity_analytics/asset_criticality';
import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setting_enabled';
import type { EntityAnalyticsRoutesDeps } from '../../types';
import { AssetCriticalityAuditActions } from '../audit';
@@ -39,7 +39,7 @@ export const assetCriticalityPublicListRoute = (
version: API_VERSIONS.public.v1,
validate: {
request: {
- query: buildRouteValidationWithZod(ListAssetCriticalityQueryParams),
+ query: buildRouteValidationWithZod(FindAssetCriticalityRecordsRequestQuery),
},
},
},
@@ -81,7 +81,7 @@ export const assetCriticalityPublicListRoute = (
},
});
- const body: AssetCriticalityListResponse = {
+ const body: FindAssetCriticalityRecordsResponse = {
records,
total,
page,
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/status.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/status.ts
index 2afa73ed5a059..9d77817a20d98 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/status.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/status.ts
@@ -7,7 +7,7 @@
import type { Logger } from '@kbn/core/server';
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
-import type { AssetCriticalityStatusResponse } from '../../../../../common/api/entity_analytics/asset_criticality';
+import type { GetAssetCriticalityStatusResponse } from '../../../../../common/api/entity_analytics';
import {
ASSET_CRITICALITY_INTERNAL_STATUS_URL,
APP_ID,
@@ -55,7 +55,7 @@ export const assetCriticalityInternalStatusRoute = (
},
});
- const body: AssetCriticalityStatusResponse = {
+ const body: GetAssetCriticalityStatusResponse = {
asset_criticality_resources_installed: result.isAssetCriticalityResourcesInstalled,
};
return response.ok({
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts
index 28c8333c5f596..7e284bfe042a0 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts
@@ -10,7 +10,7 @@ import { schema } from '@kbn/config-schema';
import Papa from 'papaparse';
import { transformError } from '@kbn/securitysolution-es-utils';
import type internal from 'stream';
-import type { AssetCriticalityBulkUploadResponse } from '../../../../../common/api/entity_analytics';
+import type { UploadAssetCriticalityRecordsResponse } from '../../../../../common/api/entity_analytics/asset_criticality/upload_asset_criticality_csv.gen';
import { CRITICALITY_CSV_MAX_SIZE_BYTES_WITH_TOLERANCE } from '../../../../../common/entity_analytics/asset_criticality';
import type { ConfigType } from '../../../../config';
import type { HapiReadableStream, SecuritySolutionRequestHandlerContext } from '../../../../types';
@@ -90,7 +90,7 @@ const handler: (
);
// type assignment here to ensure that the response body stays in sync with the API schema
- const resBody: AssetCriticalityBulkUploadResponse = { errors, stats };
+ const resBody: UploadAssetCriticalityRecordsResponse = { errors, stats };
const [eventType, event] = createAssetCriticalityProcessedFileEvent({
startTime: start,
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts
index cb3c36f450e43..20ad8173af666 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upsert.ts
@@ -8,6 +8,10 @@ import type { IKibanaResponse, KibanaResponseFactory, Logger } from '@kbn/core/s
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
import { buildRouteValidationWithZod } from '@kbn/zod-helpers';
+import {
+ CreateAssetCriticalityRecordRequestBody,
+ InternalCreateAssetCriticalityRecordRequestBody,
+} from '../../../../../common/api/entity_analytics/asset_criticality/create_asset_criticality.gen';
import type { SecuritySolutionRequestHandlerContext } from '../../../../types';
import {
ASSET_CRITICALITY_PUBLIC_URL,
@@ -17,7 +21,6 @@ import {
API_VERSIONS,
} from '../../../../../common/constants';
import { checkAndInitAssetCriticalityResources } from '../check_and_init_asset_criticality_resources';
-import { CreateSingleAssetCriticalityRequest } from '../../../../../common/api/entity_analytics';
import type { EntityAnalyticsRoutesDeps } from '../../types';
import { AssetCriticalityAuditActions } from '../audit';
import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit';
@@ -26,7 +29,7 @@ import { assertAdvancedSettingsEnabled } from '../../utils/assert_advanced_setti
type UpsertHandler = (
context: SecuritySolutionRequestHandlerContext,
request: {
- body: CreateSingleAssetCriticalityRequest;
+ body: CreateAssetCriticalityRecordRequestBody;
},
response: KibanaResponseFactory
) => Promise;
@@ -93,7 +96,7 @@ export const assetCriticalityInternalUpsertRoute = (
version: API_VERSIONS.internal.v1,
validate: {
request: {
- body: buildRouteValidationWithZod(CreateSingleAssetCriticalityRequest),
+ body: buildRouteValidationWithZod(InternalCreateAssetCriticalityRecordRequestBody),
},
},
},
@@ -118,7 +121,7 @@ export const assetCriticalityPublicUpsertRoute = (
version: API_VERSIONS.public.v1,
validate: {
request: {
- body: buildRouteValidationWithZod(CreateSingleAssetCriticalityRequest),
+ body: buildRouteValidationWithZod(CreateAssetCriticalityRecordRequestBody),
},
},
},
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/disable.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/disable.ts
index f1f0348a69e33..3501d1869d5ed 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/disable.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/disable.ts
@@ -7,7 +7,7 @@
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
-import type { RiskEngineDisableResponse } from '../../../../../common/api/entity_analytics/risk_engine/engine_disable_route.gen';
+import type { DisableRiskEngineResponse } from '../../../../../common/api/entity_analytics/risk_engine/engine_disable_route.gen';
import { RISK_ENGINE_DISABLE_URL, APP_ID } from '../../../../../common/constants';
import { TASK_MANAGER_UNAVAILABLE_ERROR } from './translations';
import { withRiskEnginePrivilegeCheck } from '../risk_engine_privileges';
@@ -71,7 +71,7 @@ export const riskEngineDisableRoute = (
try {
await riskEngineClient.disableRiskEngine({ taskManager });
- const body: RiskEngineDisableResponse = { success: true };
+ const body: DisableRiskEngineResponse = { success: true };
return response.ok({ body });
} catch (e) {
const error = transformError(e);
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/enable.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/enable.ts
index a4eed8701d1e1..9397af65675da 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/enable.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/enable.ts
@@ -7,7 +7,7 @@
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
-import type { RiskEngineEnableResponse } from '../../../../../common/api/entity_analytics/risk_engine/engine_enable_route.gen';
+import type { EnableRiskEngineResponse } from '../../../../../common/api/entity_analytics/risk_engine/engine_enable_route.gen';
import { RISK_ENGINE_ENABLE_URL, APP_ID } from '../../../../../common/constants';
import { TASK_MANAGER_UNAVAILABLE_ERROR } from './translations';
import { withRiskEnginePrivilegeCheck } from '../risk_engine_privileges';
@@ -69,7 +69,7 @@ export const riskEngineEnableRoute = (
try {
await riskEngineClient.enableRiskEngine({ taskManager });
- const body: RiskEngineEnableResponse = { success: true };
+ const body: EnableRiskEngineResponse = { success: true };
return response.ok({ body });
} catch (e) {
const error = transformError(e);
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/init.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/init.ts
index 8360f3652a7f3..9e50e0b98ccd8 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/init.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/init.ts
@@ -8,8 +8,8 @@
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
import type {
- RiskEngineInitResponse,
- RiskEngineInitResult,
+ InitRiskEngineResponse,
+ InitRiskEngineResult,
} from '../../../../../common/api/entity_analytics/risk_engine/engine_init_route.gen';
import { RISK_ENGINE_INIT_URL, APP_ID } from '../../../../../common/constants';
import { TASK_MANAGER_UNAVAILABLE_ERROR } from './translations';
@@ -64,7 +64,7 @@ export const riskEngineInitRoute = (
riskScoreDataClient,
});
- const result: RiskEngineInitResult = {
+ const result: InitRiskEngineResult = {
risk_engine_enabled: initResult.riskEngineEnabled,
risk_engine_resources_installed: initResult.riskEngineResourcesInstalled,
risk_engine_configuration_created: initResult.riskEngineConfigurationCreated,
@@ -72,7 +72,7 @@ export const riskEngineInitRoute = (
errors: initResult.errors,
};
- const initResponse: RiskEngineInitResponse = {
+ const initResponse: InitRiskEngineResponse = {
result,
};
diff --git a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/settings.ts b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/settings.ts
index 032114f7871b6..1d39fbaf18420 100644
--- a/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/settings.ts
+++ b/x-pack/plugins/security_solution/server/lib/entity_analytics/risk_engine/routes/settings.ts
@@ -7,7 +7,7 @@
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
-import type { RiskEngineSettingsResponse } from '../../../../../common/api/entity_analytics/risk_engine';
+import type { ReadRiskEngineSettingsResponse } from '../../../../../common/api/entity_analytics/risk_engine';
import { RISK_ENGINE_SETTINGS_URL, APP_ID } from '../../../../../common/constants';
import { AUDIT_CATEGORY, AUDIT_OUTCOME, AUDIT_TYPE } from '../../audit';
import type { EntityAnalyticsRoutesDeps } from '../../types';
@@ -43,7 +43,7 @@ export const riskEngineSettingsRoute = (router: EntityAnalyticsRoutesDeps['route
if (!result) {
throw new Error('Unable to get risk engine configuration');
}
- const body: RiskEngineSettingsResponse = {
+ const body: ReadRiskEngineSettingsResponse = {
range: result.range,
};
return response.ok({
diff --git a/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts b/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts
index 97a4d44fcd594..8eb46b2046c10 100644
--- a/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts
+++ b/x-pack/plugins/security_solution/server/lib/telemetry/event_based/events.ts
@@ -5,7 +5,7 @@
* 2.0.
*/
import type { EventTypeOpts } from '@kbn/core/server';
-import type { AssetCriticalityBulkUploadResponse } from '../../../../common/api/entity_analytics';
+import type { BulkUpsertAssetCriticalityRecordsResponse } from '../../../../common/api/entity_analytics';
export const RISK_SCORE_EXECUTION_SUCCESS_EVENT: EventTypeOpts<{
scoresWritten: number;
@@ -88,7 +88,7 @@ interface AssetCriticalitySystemProcessedAssignmentFileEvent {
endTime: string;
tookMs: number;
};
- result?: AssetCriticalityBulkUploadResponse['stats'];
+ result?: BulkUpsertAssetCriticalityRecordsResponse['stats'];
status: 'success' | 'partial_success' | 'fail';
}
@@ -124,7 +124,7 @@ export const ASSET_CRITICALITY_SYSTEM_PROCESSED_ASSIGNMENT_FILE_EVENT: EventType
};
interface CreateAssetCriticalityProcessedFileEvent {
- result?: AssetCriticalityBulkUploadResponse['stats'];
+ result?: BulkUpsertAssetCriticalityRecordsResponse['stats'];
startTime: Date;
endTime: Date;
}
@@ -154,7 +154,7 @@ export const createAssetCriticalityProcessedFileEvent = ({
];
};
-const getUploadStatus = (stats?: AssetCriticalityBulkUploadResponse['stats']) => {
+const getUploadStatus = (stats?: BulkUpsertAssetCriticalityRecordsResponse['stats']) => {
if (!stats) {
return 'fail';
}
diff --git a/x-pack/plugins/stack_connectors/public/connector_types/gemini/constants.tsx b/x-pack/plugins/stack_connectors/public/connector_types/gemini/constants.tsx
index 162f78efabc48..e9844a1c39b03 100644
--- a/x-pack/plugins/stack_connectors/public/connector_types/gemini/constants.tsx
+++ b/x-pack/plugins/stack_connectors/public/connector_types/gemini/constants.tsx
@@ -27,7 +27,7 @@ const contents = [
role: 'user',
parts: [
{
- text: 'Write the first line of a story about a magic backpack.',
+ text: 'Hello world!',
},
],
},
diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json
index 43b0fdd793da6..4b263c9f5a080 100644
--- a/x-pack/plugins/translations/translations/fr-FR.json
+++ b/x-pack/plugins/translations/translations/fr-FR.json
@@ -14151,13 +14151,6 @@
"xpack.enterpriseSearch.aiSearch.elser.description.elserLinkText": "Elastic Learned Sparse Encoder v2",
"xpack.enterpriseSearch.aiSearch.elserAccordion.description": "Fonctionnalités de recherche sémantique instantanée",
"xpack.enterpriseSearch.aiSearch.elserAccordion.title": "Elastic Learned Sparse Encoder",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step1.buttonLabel": "Créer un index",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step1.title": "Créez un index",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.description": "Après avoir créé un index, sélectionnez-le et cliquez sur l'onglet intitulé {pipelinesName}.",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.description.pipelinesName": "Pipelines",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.title": "Accédez à l’onglet Pipelines d’un index",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step3.description": "Localisez le panneau qui vous permet de déployer ELSER en un clic et créez un pipeline d’inférence à l’aide de ce modèle.",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step3.title": "Suivez les instructions à l’écran pour déployer ELSER",
"xpack.enterpriseSearch.aiSearch.guide.description": "Élaborez une application de recherche propulsée par l'intelligence artificielle grâce à la plateforme Elastic, y compris notre modèle ML entraîné ELSER, notre recherche vectorielle et nos capacités d'intégration, ainsi que le classement RRF pour combiner la recherche vectorielle et la recherche textuelle.",
"xpack.enterpriseSearch.aiSearch.guide.pageTitle": "Améliorez vos recherches avec l'intelligence artificielle",
"xpack.enterpriseSearch.aiSearch.linearCombinationAccordion.description": "Résultats pondérés de plusieurs classements",
@@ -14208,14 +14201,6 @@
"xpack.enterpriseSearch.aiSearch.vectorSearchAccordion.title": "Recherche vectorielle",
"xpack.enterpriseSearch.aiSearch.vectorSearchPanel.description": "Utilisez des {vectorDbCapabilities} en ajoutant des incorporations de vos modèles ML. Déployez des modèles entraînés sur des nœuds de ML Elastic et configurez des pipelines d’inférence pour ajouter automatiquement des incorporations quand vous ingérez des documents, afin de pouvoir utiliser la méthode de recherche vectorielle kNN dans _search.",
"xpack.enterpriseSearch.aiSearch.vectorSearchPanel.description.vectorDbCapabilitiesLinkText": "Fonctionnalités de bases de données vectorielles d’Elasticsearch",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.buttonLabel": "Affichez les modèles entraînés",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.guideToTrainedModelsLinkText": "Guide sur les modèles entraînés",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.title": "Apprenez à charger des modèles de ML",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step2.buttonLabel": "Créez un index",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step2.title": "Créez un index",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.description": "Accédez à l'onglet {pipelinesName} de votre index pour créer un pipeline d'inférence qui utilise votre modèle déployé.",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.description.pipelinesName": "Pipelines",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.title": "Créez un pipeline d’inférence de ML",
"xpack.enterpriseSearch.analytics..units.quickRange.last1Year": "Dernière année",
"xpack.enterpriseSearch.analytics..units.quickRange.last2Weeks": "Deux dernières semaines",
"xpack.enterpriseSearch.analytics..units.quickRange.last30Days": "30 derniers jours",
diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json
index c3ae051fef551..2a44c2da7e209 100644
--- a/x-pack/plugins/translations/translations/ja-JP.json
+++ b/x-pack/plugins/translations/translations/ja-JP.json
@@ -14107,13 +14107,6 @@
"xpack.enterpriseSearch.aiSearch.elser.description.elserLinkText": "Elastic Learned Sparse Encoder v2",
"xpack.enterpriseSearch.aiSearch.elserAccordion.description": "即時セマンティック検索機能",
"xpack.enterpriseSearch.aiSearch.elserAccordion.title": "Elastic Learned Sparse Encoder",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step1.buttonLabel": "インデックスを作成",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step1.title": "インデックスを作成",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.description": "インデックスを作成した後は、インデックスを選択し、{pipelinesName}タブをクリックします。",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.description.pipelinesName": "パイプライン",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.title": "インデックスのパイプラインタブに移動",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step3.description": "ELSERをワンクリックでデプロイし、そのモデルを使った推論パイプラインを作成できるパネルを探します。",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step3.title": "画面の指示に従い、ELSERをデプロイ",
"xpack.enterpriseSearch.aiSearch.guide.description": "当社独自の学習済みMLモデルELSER、ベクトル検索と埋め込み機能、ベクトル検索とテキスト検索を組み合わせたRRFランキングなど、Elasticプラットフォームを使用して、AI検索を活用したアプリケーションを構築できます。",
"xpack.enterpriseSearch.aiSearch.guide.pageTitle": "AIで検索を強化",
"xpack.enterpriseSearch.aiSearch.linearCombinationAccordion.description": "複数のランキングから重み付けがされた結果",
@@ -14164,14 +14157,6 @@
"xpack.enterpriseSearch.aiSearch.vectorSearchAccordion.title": "ベクトル検索",
"xpack.enterpriseSearch.aiSearch.vectorSearchPanel.description": "MLモデルから埋め込みを追加して、{vectorDbCapabilities}を使用します。Elastic MLノードに学習済みモデルをデプロイし、推論パイプラインを設定して、ドキュメントをインジェストしたときに自動的に埋め込みが追加されるようにします。これにより、_searchでkNNベクトル検索方法を使用できます。",
"xpack.enterpriseSearch.aiSearch.vectorSearchPanel.description.vectorDbCapabilitiesLinkText": "ElasticsearchのベクトルDB機能",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.buttonLabel": "学習済みモデルを表示",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.guideToTrainedModelsLinkText": "学習済みモデルのガイド",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.title": "MLモデルのアップロード方法",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step2.buttonLabel": "インデックスを作成",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step2.title": "インデックスを作成",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.description": "インデックスの{pipelinesName}タブに移動し、デプロイされたモデルで使用する推論パイプラインを作成します。",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.description.pipelinesName": "パイプライン",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.title": "ML推論パイプラインを作成",
"xpack.enterpriseSearch.analytics..units.quickRange.last1Year": "過去1年間",
"xpack.enterpriseSearch.analytics..units.quickRange.last2Weeks": "過去 2 週間",
"xpack.enterpriseSearch.analytics..units.quickRange.last30Days": "過去30日間",
diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json
index f96a1de934d35..25a0b95a991fd 100644
--- a/x-pack/plugins/translations/translations/zh-CN.json
+++ b/x-pack/plugins/translations/translations/zh-CN.json
@@ -14171,13 +14171,6 @@
"xpack.enterpriseSearch.aiSearch.elser.description.elserLinkText": "Elastic Learned Sparse Encoder v2",
"xpack.enterpriseSearch.aiSearch.elserAccordion.description": "即时语义搜索功能",
"xpack.enterpriseSearch.aiSearch.elserAccordion.title": "Elastic Learned Sparse Encoder",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step1.buttonLabel": "创建索引",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step1.title": "创建索引",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.description": "创建索引后,请选中该索引,然后单击 {pipelinesName} 选项卡。",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.description.pipelinesName": "管道",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step2.title": "导航到索引的“管道”选项卡",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step3.description": "查找允许您一键部署 ELSER 并使用该模型创建推理管道的面板。",
- "xpack.enterpriseSearch.aiSearch.elserPanel.step3.title": "按照屏幕上显示的说明部署 ELSER",
"xpack.enterpriseSearch.aiSearch.guide.description": "使用 Elastic 平台,包括我们专有的已训练 ML 模型 ELSER、矢量搜索和嵌入功能,以及用于组合矢量和文本搜索的 RRF 排名,构建 AI 搜索驱动式应用程序。",
"xpack.enterpriseSearch.aiSearch.guide.pageTitle": "利用 AI 增强您的搜索功能",
"xpack.enterpriseSearch.aiSearch.linearCombinationAccordion.description": "来自多个排名的加权结果",
@@ -14228,14 +14221,6 @@
"xpack.enterpriseSearch.aiSearch.vectorSearchAccordion.title": "矢量搜索",
"xpack.enterpriseSearch.aiSearch.vectorSearchPanel.description": "通过添加来自 ML 模型的嵌入来使用{vectorDbCapabilities}。在 Elastic ML 节点上部署已训练模型并设置推理管道,以在采集文档时自动添加嵌入,便于您在 _search 中使用 kNN 矢量搜索方法。",
"xpack.enterpriseSearch.aiSearch.vectorSearchPanel.description.vectorDbCapabilitiesLinkText": "Elasticsearch 的矢量 DB 功能",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.buttonLabel": "查看已训练模型",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.guideToTrainedModelsLinkText": "已训练模型指南",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step1.title": "了解如何上传 ML 模型",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step2.buttonLabel": "创建索引",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step2.title": "创建索引",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.description": "导航到您索引的 {pipelinesName} 选项卡,以创建使用已部署模型的推理管道。",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.description.pipelinesName": "管道",
- "xpack.enterpriseSearch.aiSearch.vectorSearchPanel.step3.title": "创建 ML 推理管道",
"xpack.enterpriseSearch.analytics..units.quickRange.last1Year": "过去 1 年",
"xpack.enterpriseSearch.analytics..units.quickRange.last2Weeks": "过去 2 周",
"xpack.enterpriseSearch.analytics..units.quickRange.last30Days": "过去 30 天",
diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/gemini.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/gemini.ts
index d483d11db96ec..54eebf207e7d7 100644
--- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/gemini.ts
+++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/connector_types/gemini.ts
@@ -310,7 +310,7 @@ export default function geminiTest({ getService }: FtrProviderContext) {
role: 'user',
parts: [
{
- text: 'Write the first line of a story about a magic backpack.',
+ text: 'Hello world!',
},
],
},
@@ -325,7 +325,7 @@ export default function geminiTest({ getService }: FtrProviderContext) {
contents: [
{
role: 'user',
- parts: [{ text: 'Write the first line of a story about a magic backpack.' }],
+ parts: [{ text: 'Hello world!' }],
},
],
generation_config: { temperature: 0, maxOutputTokens: 8192 },
diff --git a/x-pack/test/api_integration/services/security_solution_api.gen.ts b/x-pack/test/api_integration/services/security_solution_api.gen.ts
index f5089b489a617..91ae460bbb563 100644
--- a/x-pack/test/api_integration/services/security_solution_api.gen.ts
+++ b/x-pack/test/api_integration/services/security_solution_api.gen.ts
@@ -26,13 +26,17 @@ import { BulkDeleteRulesRequestBodyInput } from '@kbn/security-solution-plugin/c
import { BulkDeleteRulesPostRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_crud/bulk_delete_rules/bulk_delete_rules_route.gen';
import { BulkPatchRulesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_crud/bulk_patch_rules/bulk_patch_rules_route.gen';
import { BulkUpdateRulesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_crud/bulk_update_rules/bulk_update_rules_route.gen';
+import { BulkUpsertAssetCriticalityRecordsRequestBodyInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/bulk_upload_asset_criticality.gen';
import { CreateAlertsMigrationRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals_migration/create_signals_migration/create_signals_migration.gen';
+import { CreateAssetCriticalityRecordRequestBodyInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/create_asset_criticality.gen';
import { CreateRuleRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/create_rule/create_rule_route.gen';
import {
CreateUpdateProtectionUpdatesNoteRequestParamsInput,
CreateUpdateProtectionUpdatesNoteRequestBodyInput,
} from '@kbn/security-solution-plugin/common/api/endpoint/protection_updates_note/protection_updates_note.gen';
+import { DeleteAssetCriticalityRecordRequestQueryInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/delete_asset_criticality.gen';
import { DeleteRuleRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/delete_rule/delete_rule_route.gen';
+import { DeprecatedTriggerRiskScoreCalculationRequestBodyInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/risk_engine/entity_calculation_route.gen';
import { EndpointIsolateRedirectRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/isolate_route.gen';
import { EndpointUnisolateRedirectRequestBodyInput } from '@kbn/security-solution-plugin/common/api/endpoint/actions/unisolate_route.gen';
import {
@@ -40,9 +44,11 @@ import {
ExportRulesRequestBodyInput,
} from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/export_rules/export_rules_route.gen';
import { FinalizeAlertsMigrationRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals_migration/finalize_signals_migration/finalize_signals_migration.gen';
+import { FindAssetCriticalityRecordsRequestQueryInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/list_asset_criticality.gen';
import { FindRulesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/find_rules/find_rules_route.gen';
import { GetAgentPolicySummaryRequestQueryInput } from '@kbn/security-solution-plugin/common/api/endpoint/policy/policy.gen';
import { GetAlertsMigrationStatusRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals_migration/get_signals_migration_status/get_signals_migration_status.gen';
+import { GetAssetCriticalityRecordRequestQueryInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/get_asset_criticality.gen';
import {
GetEndpointSuggestionsRequestParamsInput,
GetEndpointSuggestionsRequestBodyInput,
@@ -58,18 +64,22 @@ import {
GetRuleExecutionResultsRequestParamsInput,
} from '@kbn/security-solution-plugin/common/api/detection_engine/rule_monitoring/rule_execution_logs/get_rule_execution_results/get_rule_execution_results_route.gen';
import { ImportRulesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/import_rules/import_rules_route.gen';
+import { InternalCreateAssetCriticalityRecordRequestBodyInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/create_asset_criticality.gen';
+import { InternalDeleteAssetCriticalityRecordRequestQueryInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/asset_criticality/delete_asset_criticality.gen';
import { ManageAlertTagsRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/alert_tags/set_alert_tags/set_alert_tags.gen';
import { PatchRuleRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/patch_rule/patch_rule_route.gen';
import {
PerformBulkActionRequestQueryInput,
PerformBulkActionRequestBodyInput,
} from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/bulk_actions/bulk_actions_route.gen';
+import { PreviewRiskScoreRequestBodyInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/risk_engine/preview_route.gen';
import { ReadRuleRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/read_rule/read_rule_route.gen';
import { RulePreviewRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_preview/rule_preview.gen';
import { SearchAlertsRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals/query_signals/query_signals_route.gen';
import { SetAlertAssigneesRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/alert_assignees/set_alert_assignees_route.gen';
import { SetAlertsStatusRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/signals/set_signal_status/set_signals_status_route.gen';
import { SuggestUserProfilesRequestQueryInput } from '@kbn/security-solution-plugin/common/api/detection_engine/users/suggest_user_profiles_route.gen';
+import { TriggerRiskScoreCalculationRequestBodyInput } from '@kbn/security-solution-plugin/common/api/entity_analytics/risk_engine/entity_calculation_route.gen';
import { UpdateRuleRequestBodyInput } from '@kbn/security-solution-plugin/common/api/detection_engine/rule_management/crud/update_rule/update_rule_route.gen';
import { FtrProviderContext } from '../ftr_provider_context';
@@ -153,6 +163,14 @@ after 30 days. It also deletes other artifacts specific to the migration impleme
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
+ bulkUpsertAssetCriticalityRecords(props: BulkUpsertAssetCriticalityRecordsProps) {
+ return supertest
+ .post('/api/asset_criticality/bulk')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .send(props.body as object);
+ },
createAlertsIndex() {
return supertest
.post('/api/detection_engine/index')
@@ -173,6 +191,14 @@ Migrations are initiated per index. While the process is neither destructive nor
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
+ createAssetCriticalityRecord(props: CreateAssetCriticalityRecordProps) {
+ return supertest
+ .post('/api/asset_criticality')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .send(props.body as object);
+ },
/**
* Create a new detection rule.
*/
@@ -201,6 +227,14 @@ Migrations are initiated per index. While the process is neither destructive nor
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
},
+ deleteAssetCriticalityRecord(props: DeleteAssetCriticalityRecordProps) {
+ return supertest
+ .delete('/api/asset_criticality')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .query(props.query);
+ },
/**
* Delete a detection rule using the `rule_id` or `id` field.
*/
@@ -212,6 +246,31 @@ Migrations are initiated per index. While the process is neither destructive nor
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.query(props.query);
},
+ /**
+ * Calculates and persists Risk Scores for an entity, returning the calculated risk score.
+ */
+ deprecatedTriggerRiskScoreCalculation(props: DeprecatedTriggerRiskScoreCalculationProps) {
+ return supertest
+ .post('/api/risk_scores/calculation/entity')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .send(props.body as object);
+ },
+ disableRiskEngine() {
+ return supertest
+ .post('/internal/risk_score/engine/disable')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
+ },
+ enableRiskEngine() {
+ return supertest
+ .post('/internal/risk_score/engine/enable')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
+ },
endpointIsolateRedirect(props: EndpointIsolateRedirectProps) {
return supertest
.post('/api/endpoint/isolate')
@@ -259,6 +318,14 @@ finalize it.
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
+ findAssetCriticalityRecords(props: FindAssetCriticalityRecordsProps) {
+ return supertest
+ .post('/api/asset_criticality/list')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .query(props.query);
+ },
/**
* Retrieve a paginated list of detection rules. By default, the first page is returned, with 20 results per page.
*/
@@ -296,6 +363,21 @@ finalize it.
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.query(props.query);
},
+ getAssetCriticalityRecord(props: GetAssetCriticalityRecordProps) {
+ return supertest
+ .get('/api/asset_criticality')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .query(props.query);
+ },
+ getAssetCriticalityStatus() {
+ return supertest
+ .get('/internal/asset_criticality/status')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
+ },
getEndpointSuggestions(props: GetEndpointSuggestionsProps) {
return supertest
.post(replaceParams('/api/endpoint/suggestions/{suggestion_type}', props.params))
@@ -345,6 +427,16 @@ detection engine rules.
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
},
+ /**
+ * Returns the status of both the legacy transform-based risk engine, as well as the new risk engine
+ */
+ getRiskEngineStatus() {
+ return supertest
+ .get('/internal/risk_score/engine/status')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
+ },
getRuleExecutionEvents(props: GetRuleExecutionEventsProps) {
return supertest
.put(
@@ -379,6 +471,16 @@ detection engine rules.
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.query(props.query);
},
+ /**
+ * Initializes the Risk Engine by creating the necessary indices and mappings, removing old transforms, and starting the new risk engine
+ */
+ initRiskEngine() {
+ return supertest
+ .post('/internal/risk_score/engine/init')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
+ },
/**
* Install and update all Elastic prebuilt detection rules and Timelines.
*/
@@ -389,6 +491,29 @@ detection engine rules.
.set(ELASTIC_HTTP_VERSION_HEADER, '2023-10-31')
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
},
+ internalCreateAssetCriticalityRecord(props: InternalCreateAssetCriticalityRecordProps) {
+ return supertest
+ .post('/internal/asset_criticality')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .send(props.body as object);
+ },
+ internalDeleteAssetCriticalityRecord(props: InternalDeleteAssetCriticalityRecordProps) {
+ return supertest
+ .delete('/internal/asset_criticality')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .query(props.query);
+ },
+ internalUploadAssetCriticalityRecords() {
+ return supertest
+ .post('/internal/asset_criticality/upload_csv')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
+ },
/**
* And tags to detection alerts, and remove them from alerts.
> info
@@ -426,6 +551,24 @@ detection engine rules.
.send(props.body as object)
.query(props.query);
},
+ /**
+ * Calculates and returns a list of Risk Scores, sorted by identifier_type and risk score.
+ */
+ previewRiskScore(props: PreviewRiskScoreProps) {
+ return supertest
+ .post('/internal/risk_score/preview')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .send(props.body as object);
+ },
+ readRiskEngineSettings() {
+ return supertest
+ .get('/internal/risk_score/engine/settings')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
+ },
/**
* Retrieve a detection rule using the `rule_id` or `id` field.
*/
@@ -502,6 +645,17 @@ detection engine rules.
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.query(props.query);
},
+ /**
+ * Calculates and persists Risk Scores for an entity, returning the calculated risk score.
+ */
+ triggerRiskScoreCalculation(props: TriggerRiskScoreCalculationProps) {
+ return supertest
+ .post('/internal/risk_score/calculation/entity')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
+ .send(props.body as object);
+ },
/**
* Update a detection rule using the `rule_id` or `id` field. The original rule is replaced, and all unspecified fields are deleted.
> info
@@ -516,6 +670,13 @@ detection engine rules.
.set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana')
.send(props.body as object);
},
+ uploadAssetCriticalityRecords() {
+ return supertest
+ .post('/api/asset_criticality/upload_csv')
+ .set('kbn-xsrf', 'true')
+ .set(ELASTIC_HTTP_VERSION_HEADER, '1')
+ .set(X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'kibana');
+ },
};
}
@@ -537,9 +698,15 @@ export interface BulkPatchRulesProps {
export interface BulkUpdateRulesProps {
body: BulkUpdateRulesRequestBodyInput;
}
+export interface BulkUpsertAssetCriticalityRecordsProps {
+ body: BulkUpsertAssetCriticalityRecordsRequestBodyInput;
+}
export interface CreateAlertsMigrationProps {
body: CreateAlertsMigrationRequestBodyInput;
}
+export interface CreateAssetCriticalityRecordProps {
+ body: CreateAssetCriticalityRecordRequestBodyInput;
+}
export interface CreateRuleProps {
body: CreateRuleRequestBodyInput;
}
@@ -547,9 +714,15 @@ export interface CreateUpdateProtectionUpdatesNoteProps {
params: CreateUpdateProtectionUpdatesNoteRequestParamsInput;
body: CreateUpdateProtectionUpdatesNoteRequestBodyInput;
}
+export interface DeleteAssetCriticalityRecordProps {
+ query: DeleteAssetCriticalityRecordRequestQueryInput;
+}
export interface DeleteRuleProps {
query: DeleteRuleRequestQueryInput;
}
+export interface DeprecatedTriggerRiskScoreCalculationProps {
+ body: DeprecatedTriggerRiskScoreCalculationRequestBodyInput;
+}
export interface EndpointIsolateRedirectProps {
body: EndpointIsolateRedirectRequestBodyInput;
}
@@ -563,6 +736,9 @@ export interface ExportRulesProps {
export interface FinalizeAlertsMigrationProps {
body: FinalizeAlertsMigrationRequestBodyInput;
}
+export interface FindAssetCriticalityRecordsProps {
+ query: FindAssetCriticalityRecordsRequestQueryInput;
+}
export interface FindRulesProps {
query: FindRulesRequestQueryInput;
}
@@ -572,6 +748,9 @@ export interface GetAgentPolicySummaryProps {
export interface GetAlertsMigrationStatusProps {
query: GetAlertsMigrationStatusRequestQueryInput;
}
+export interface GetAssetCriticalityRecordProps {
+ query: GetAssetCriticalityRecordRequestQueryInput;
+}
export interface GetEndpointSuggestionsProps {
params: GetEndpointSuggestionsRequestParamsInput;
body: GetEndpointSuggestionsRequestBodyInput;
@@ -593,6 +772,12 @@ export interface GetRuleExecutionResultsProps {
export interface ImportRulesProps {
query: ImportRulesRequestQueryInput;
}
+export interface InternalCreateAssetCriticalityRecordProps {
+ body: InternalCreateAssetCriticalityRecordRequestBodyInput;
+}
+export interface InternalDeleteAssetCriticalityRecordProps {
+ query: InternalDeleteAssetCriticalityRecordRequestQueryInput;
+}
export interface ManageAlertTagsProps {
body: ManageAlertTagsRequestBodyInput;
}
@@ -603,6 +788,9 @@ export interface PerformBulkActionProps {
query: PerformBulkActionRequestQueryInput;
body: PerformBulkActionRequestBodyInput;
}
+export interface PreviewRiskScoreProps {
+ body: PreviewRiskScoreRequestBodyInput;
+}
export interface ReadRuleProps {
query: ReadRuleRequestQueryInput;
}
@@ -621,6 +809,9 @@ export interface SetAlertsStatusProps {
export interface SuggestUserProfilesProps {
query: SuggestUserProfilesRequestQueryInput;
}
+export interface TriggerRiskScoreCalculationProps {
+ body: TriggerRiskScoreCalculationRequestBodyInput;
+}
export interface UpdateRuleProps {
body: UpdateRuleRequestBodyInput;
}
diff --git a/x-pack/test/functional/page_objects/search_playground_page.ts b/x-pack/test/functional/page_objects/search_playground_page.ts
index 133d988f04653..97e53e87ed2f9 100644
--- a/x-pack/test/functional/page_objects/search_playground_page.ts
+++ b/x-pack/test/functional/page_objects/search_playground_page.ts
@@ -19,7 +19,35 @@ export function SearchPlaygroundPageProvider({ getService }: FtrProviderContext)
await testSubjects.click('saveButton');
};
+ const SESSION_KEY = 'search_playground_session';
+
return {
+ session: {
+ async clearSession(): Promise {
+ await browser.setLocalStorageItem(SESSION_KEY, '{}');
+ },
+
+ async setSession(): Promise {
+ await browser.setLocalStorageItem(
+ SESSION_KEY,
+ JSON.stringify({
+ prompt: 'You are a fireman in london that helps answering question-answering tasks.',
+ })
+ );
+ },
+
+ async expectSession(): Promise {
+ const session = (await browser.getLocalStorageItem(SESSION_KEY)) || '{}';
+ const state = JSON.parse(session);
+ expect(state.prompt).to.be('You are an assistant for question-answering tasks.');
+ expect(state.doc_size).to.be(3);
+ expect(state.elasticsearch_query).eql({
+ retriever: {
+ standard: { query: { multi_match: { query: '{query}', fields: ['baz'] } } },
+ },
+ });
+ },
+ },
PlaygroundStartChatPage: {
async expectPlaygroundStartChatPageComponentsToExist() {
await testSubjects.existOrFail('setupPage');
@@ -85,6 +113,13 @@ export function SearchPlaygroundPageProvider({ getService }: FtrProviderContext)
await testSubjects.existOrFail('chatPage');
},
+ async expectPromptToBe(text: string) {
+ await testSubjects.existOrFail('instructionsPrompt');
+ const instructionsPromptElement = await testSubjects.find('instructionsPrompt');
+ const promptInstructions = await instructionsPromptElement.getVisibleText();
+ expect(promptInstructions).to.contain(text);
+ },
+
async expectChatWindowLoaded() {
expect(await testSubjects.getAttribute('viewModeSelector', 'disabled')).to.be(null);
expect(await testSubjects.isEnabled('dataSourceActionButton')).to.be(true);
diff --git a/x-pack/test/security_solution_api_integration/config/services/security_solution_edr_workflows_roles_users.ts b/x-pack/test/security_solution_api_integration/config/services/security_solution_edr_workflows_roles_users.ts
index f364943164322..92e0cc9ba1f13 100644
--- a/x-pack/test/security_solution_api_integration/config/services/security_solution_edr_workflows_roles_users.ts
+++ b/x-pack/test/security_solution_api_integration/config/services/security_solution_edr_workflows_roles_users.ts
@@ -5,6 +5,7 @@
* 2.0.
*/
+import { Role } from '@kbn/security-plugin/common';
import {
EndpointSecurityRoleNames,
ENDPOINT_SECURITY_ROLE_NAMES,
@@ -61,9 +62,25 @@ export function RolesUsersProvider({ getService }: FtrProviderContext) {
await security.role.create(predefinedRole, roleConfig);
}
if (customRole) {
- await security.role.create(customRole.roleName, {
- permissions: { feature: { siem: [...customRole.extraPrivileges] } },
- });
+ const role: Omit = {
+ description: '',
+ elasticsearch: {
+ cluster: [],
+ indices: [],
+ run_as: [],
+ },
+ kibana: [
+ {
+ spaces: ['*'],
+ base: [],
+ feature: {
+ siem: customRole.extraPrivileges,
+ },
+ },
+ ],
+ };
+
+ await security.role.create(customRole.roleName, role);
}
},
diff --git a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/response_actions/trial_license_complete_tier/execute.ts b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/response_actions/trial_license_complete_tier/execute.ts
index 4178fd80b653a..6e50f67e3510d 100644
--- a/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/response_actions/trial_license_complete_tier/execute.ts
+++ b/x-pack/test/security_solution_api_integration/test_suites/edr_workflows/response_actions/trial_license_complete_tier/execute.ts
@@ -6,14 +6,21 @@
*/
import { wrapErrorAndRejectPromise } from '@kbn/security-solution-plugin/common/endpoint/data_loaders/utils';
import expect from '@kbn/expect';
-import { EXECUTE_ROUTE } from '@kbn/security-solution-plugin/common/endpoint/constants';
+import {
+ ACTION_AGENT_FILE_INFO_ROUTE,
+ EXECUTE_ROUTE,
+} from '@kbn/security-solution-plugin/common/endpoint/constants';
import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data';
+import { ActionDetails } from '@kbn/security-solution-plugin/common/endpoint/types';
+import { getFileDownloadId } from '@kbn/security-solution-plugin/common/endpoint/service/response_actions/get_file_download_id';
import { FtrProviderContext } from '../../../../ftr_provider_context_edr_workflows';
import { ROLE } from '../../../../config/services/security_solution_edr_workflows_roles_users';
export default function ({ getService }: FtrProviderContext) {
const supertestWithoutAuth = getService('supertestWithoutAuth');
const endpointTestResources = getService('endpointTestResources');
+ const rolesUsersProvider = getService('rolesUsersProvider');
+
// @skipInServerlessMKI - this test uses internal index manipulation in before/after hooks
describe('@ess @serverless @skipInServerlessMKI Endpoint `execute` response action', function () {
let indexedData: IndexedHostsAndAlertsResponse;
@@ -150,5 +157,66 @@ export default function ({ getService }: FtrProviderContext) {
expect(data.parameters.command).to.eql('ls -la');
expect(data.parameters.timeout).to.eql(2000);
});
+
+ // Test checks to ensure API works with a custom role
+ describe('@skipInServerless @skipInServerlessMKI and with minimal authz', () => {
+ const username = 'execute_limited';
+ const password = 'changeme';
+ let fileInfoApiRoutePath: string = '';
+
+ before(async () => {
+ await rolesUsersProvider.createRole({
+ customRole: {
+ roleName: username,
+ extraPrivileges: ['minimal_all', 'execute_operations_all'],
+ },
+ });
+ await rolesUsersProvider.createUser({ name: username, password, roles: [username] });
+
+ const {
+ body: { data },
+ } = await supertestWithoutAuth
+ .post(EXECUTE_ROUTE)
+ .auth(username, password)
+ .set('kbn-xsrf', 'true')
+ .set('Elastic-Api-Version', '2023-10-31')
+ .send({ endpoint_ids: [agentId], parameters: { command: 'ls -la' } })
+ .expect(200);
+
+ const actionDetails = data as ActionDetails;
+
+ fileInfoApiRoutePath = ACTION_AGENT_FILE_INFO_ROUTE.replace('{action_id}', data.id).replace(
+ '{file_id}',
+ getFileDownloadId(actionDetails)
+ );
+ });
+
+ after(async () => {
+ await rolesUsersProvider.deleteRoles([username]);
+ await rolesUsersProvider.deleteUsers([username]);
+ });
+
+ it('should have access to file info api', async () => {
+ await supertestWithoutAuth
+ .get(fileInfoApiRoutePath)
+ .auth(username, password)
+ .set('kbn-xsrf', 'true')
+ .set('Elastic-Api-Version', '2023-10-31')
+ // We expect 404 because the indexes with the file info don't exist.
+ // The key here is that we do NOT get a 401 or 403
+ .expect(404);
+ });
+
+ it('should have access to file download api', async () => {
+ await supertestWithoutAuth
+ .get(`${fileInfoApiRoutePath}/download`)
+ .auth(username, password)
+ .set('kbn-xsrf', 'true')
+ .set('Elastic-Api-Version', '2023-10-31')
+ // We expect 404 because the indexes with the file info don't exist.
+ // The key here is that we do NOT get a 401 or 403
+ .expect(404);
+ });
+ });
});
}
diff --git a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts
index 9ae70f540f897..11343e077eeaf 100644
--- a/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts
+++ b/x-pack/test/security_solution_api_integration/test_suites/entity_analytics/utils/asset_criticality.ts
@@ -23,7 +23,7 @@ import {
import type {
AssetCriticalityRecord,
CreateAssetCriticalityRecord,
- ListAssetCriticalityQueryParams,
+ FindAssetCriticalityRecordsRequestQuery,
} from '@kbn/security-solution-plugin/common/api/entity_analytics';
import type { Client } from '@elastic/elasticsearch';
import type { ToolingLog } from '@kbn/tooling-log';
@@ -187,7 +187,7 @@ export const assetCriticalityRouteHelpersFactory = (
.expect(expectStatusCode);
},
list: async (
- opts: ListAssetCriticalityQueryParams = {},
+ opts: FindAssetCriticalityRecordsRequestQuery = {},
{ expectStatusCode }: { expectStatusCode: number } = { expectStatusCode: 200 }
) => {
const qs = querystring.stringify(opts);
diff --git a/x-pack/test/security_solution_api_integration/tsconfig.json b/x-pack/test/security_solution_api_integration/tsconfig.json
index 8584cebd03edb..a4b454cb27870 100644
--- a/x-pack/test/security_solution_api_integration/tsconfig.json
+++ b/x-pack/test/security_solution_api_integration/tsconfig.json
@@ -46,5 +46,6 @@
"@kbn/utility-types",
"@kbn/timelines-plugin",
"@kbn/dev-cli-runner",
+ "@kbn/security-plugin",
]
}
diff --git a/x-pack/test/ui_capabilities/security_and_spaces/tests/catalogue.ts b/x-pack/test/ui_capabilities/security_and_spaces/tests/catalogue.ts
index b1ff2187bc574..9b34220ee75f3 100644
--- a/x-pack/test/ui_capabilities/security_and_spaces/tests/catalogue.ts
+++ b/x-pack/test/ui_capabilities/security_and_spaces/tests/catalogue.ts
@@ -69,6 +69,7 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
'enterpriseSearchApplications',
'enterpriseSearchAISearch',
'enterpriseSearchVectorSearch',
+ 'enterpriseSearchSemanticSearch',
'enterpriseSearchElasticsearch',
'appSearch',
'workplaceSearch',
@@ -99,6 +100,7 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
'enterpriseSearchApplications',
'enterpriseSearchAISearch',
'enterpriseSearchVectorSearch',
+ 'enterpriseSearchSemanticSearch',
'enterpriseSearchElasticsearch',
'appSearch',
'observabilityAIAssistant',
diff --git a/x-pack/test/ui_capabilities/security_and_spaces/tests/nav_links.ts b/x-pack/test/ui_capabilities/security_and_spaces/tests/nav_links.ts
index fb7b3a112f6de..b2955ade938b1 100644
--- a/x-pack/test/ui_capabilities/security_and_spaces/tests/nav_links.ts
+++ b/x-pack/test/ui_capabilities/security_and_spaces/tests/nav_links.ts
@@ -56,6 +56,7 @@ export default function navLinksTests({ getService }: FtrProviderContext) {
'enterpriseSearchApplications',
'enterpriseSearchAISearch',
'enterpriseSearchVectorSearch',
+ 'enterpriseSearchSemanticSearch',
'enterpriseSearchElasticsearch',
'appSearch',
'workplaceSearch'
@@ -76,6 +77,7 @@ export default function navLinksTests({ getService }: FtrProviderContext) {
'enterpriseSearchApplications',
'enterpriseSearchAISearch',
'enterpriseSearchVectorSearch',
+ 'enterpriseSearchSemanticSearch',
'enterpriseSearchElasticsearch',
'observabilityAIAssistant',
'appSearch',
diff --git a/x-pack/test/ui_capabilities/spaces_only/tests/catalogue.ts b/x-pack/test/ui_capabilities/spaces_only/tests/catalogue.ts
index a52cb46b77c9f..18693d4699f53 100644
--- a/x-pack/test/ui_capabilities/spaces_only/tests/catalogue.ts
+++ b/x-pack/test/ui_capabilities/spaces_only/tests/catalogue.ts
@@ -33,6 +33,7 @@ export default function catalogueTests({ getService }: FtrProviderContext) {
'enterpriseSearchApplications',
'enterpriseSearchAISearch',
'enterpriseSearchVectorSearch',
+ 'enterpriseSearchSemanticSearch',
'enterpriseSearchElasticsearch',
'appSearch',
'workplaceSearch',
diff --git a/x-pack/test/ui_capabilities/spaces_only/tests/nav_links.ts b/x-pack/test/ui_capabilities/spaces_only/tests/nav_links.ts
index 2778b8e54a13a..f5559940ff812 100644
--- a/x-pack/test/ui_capabilities/spaces_only/tests/nav_links.ts
+++ b/x-pack/test/ui_capabilities/spaces_only/tests/nav_links.ts
@@ -25,6 +25,7 @@ export default function navLinksTests({ getService }: FtrProviderContext) {
'enterpriseSearchApplications',
'enterpriseSearchAISearch',
'enterpriseSearchVectorSearch',
+ 'enterpriseSearchSemanticSearch',
'enterpriseSearchElasticsearch',
'appSearch',
'workplaceSearch',
diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/serverless_metering/cloud_security_metering.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/serverless_metering/cloud_security_metering.ts
index c1ce48215e2e2..49c223c8d1424 100644
--- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/serverless_metering/cloud_security_metering.ts
+++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/serverless_metering/cloud_security_metering.ts
@@ -40,7 +40,8 @@ export default function (providerContext: FtrProviderContext) {
The task manager is running by default in security serverless project in the background and sending usage API requests to the usage API.
This test mocks the usage API server and intercepts the usage API request sent by the metering background task manager.
*/
- describe('Intercept the usage API request sent by the metering background task manager', function () {
+ // FLAKY: https://github.com/elastic/kibana/issues/188660
+ describe.skip('Intercept the usage API request sent by the metering background task manager', function () {
this.tags(['skipMKI']);
let mockUsageApiServer: http.Server;
diff --git a/x-pack/test_serverless/functional/test_suites/search/search_playground/playground_overview.ts b/x-pack/test_serverless/functional/test_suites/search/search_playground/playground_overview.ts
index 2e8538e154cbe..656671f277d75 100644
--- a/x-pack/test_serverless/functional/test_suites/search/search_playground/playground_overview.ts
+++ b/x-pack/test_serverless/functional/test_suites/search/search_playground/playground_overview.ts
@@ -137,6 +137,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
await createConnector();
await createIndex();
await browser.refresh();
+ await pageObjects.searchPlayground.session.clearSession();
await pageObjects.searchPlayground.PlaygroundChatPage.navigateToChatPage();
});
it('loads successfully', async () => {
@@ -153,6 +154,8 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
) === undefined
);
+ await pageObjects.searchPlayground.session.expectSession();
+
await pageObjects.searchPlayground.PlaygroundChatPage.sendQuestion();
const conversationSimulator = await conversationInterceptor.waitForIntercept();
@@ -180,6 +183,15 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) {
it('save selected fields between modes', async () => {
await pageObjects.searchPlayground.PlaygroundChatPage.expectSaveFieldsBetweenModes();
});
+
+ it('loads a session from localstorage', async () => {
+ await pageObjects.searchPlayground.session.setSession();
+ await browser.refresh();
+ await pageObjects.searchPlayground.PlaygroundChatPage.navigateToChatPage();
+ await pageObjects.searchPlayground.PlaygroundChatPage.expectPromptToBe(
+ 'You are a fireman in london that helps answering question-answering tasks.'
+ );
+ });
});
after(async () => {