From 131ade82f6d863779440c54683e25fe84859caa5 Mon Sep 17 00:00:00 2001 From: Pablo Machado Date: Tue, 25 Jun 2024 15:48:00 +0200 Subject: [PATCH 01/22] [Security Solution] Update serverless FTR tests to not run with operator privileges (#185870) ## Summary * ***Create a new service that replaced the serverless `supertest` with a custom implementation that adds auth headers*** * `username` updates * Update `SessionManager` to store `username` * Create and export `securitySolutionUtils` to return the `username` * Update tests to use the `getUsername` helper * Create a helper that allows switching serverless roles on a test ```js export default ({ getService }: FtrProviderContext) => { const utils = getService('securitySolutionUtils'); describe('@ess @serverless my_test', () => { let supertest: TestAgent; before(async () => { supertest = await utils.createSuperTest('admin'); }); ... ``` * Update FTR tests [README file](https://github.com/machadoum/kibana/blob/siem-ea-183512/x-pack/test/security_solution_api_integration/README.md#testing-with-serverless-roles) with further details Flaky test runner: https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6320 ### Know issues * Currently `utils.createSuperTest('viewer')` fails on the API creation. It will be fixed by @elastic/kibana-security https://github.com/elastic/kibana/issues/184948 ### Checklist Delete any items that are not applicable to this PR. - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed --- .../README.md | 40 ++++++++++- .../config/ess/config.base.ts | 2 +- .../config/ess/services.ts | 2 + .../serverless/config.base.essentials.ts | 2 +- .../config/serverless/services.ts | 4 ++ .../services/security_solution_ess_utils.ts | 22 ++++++ .../security_solution_serverless_supertest.ts | 15 ++++ .../security_solution_serverless_utils.ts | 68 +++++++++++++++++++ .../config/services/types.ts | 13 ++++ .../create_rule_exceptions.ts | 19 +++--- .../execution_logic/esql.ts | 8 +-- .../execution_logic/indicator_match.ts | 12 ++-- .../execution_logic/new_terms.ts | 7 +- .../perform_bulk_action.ts | 6 +- .../create_ml_rules_privileges.ts | 4 +- .../create_rules.ts | 8 +-- .../create_rules_bulk.ts | 6 +- .../create_rules.ts | 14 ++-- .../delete_rules.ts | 9 ++- .../delete_rules_bulk.ts | 19 +++--- .../delete_rules.ts | 10 ++- .../delete_rules_bulk.ts | 20 +++--- .../patch_rules.ts | 15 ++-- .../patch_rules_bulk.ts | 29 ++++---- .../patch_rules.ts | 30 ++++---- .../patch_rules_bulk.ts | 42 +++++------- .../patch_rules_ess.ts | 6 +- .../find_rules.ts | 7 +- .../read_rules.ts | 9 ++- .../trial_license_complete_tier/find_rules.ts | 12 ++-- .../find_rules_ess.ts | 6 +- .../trial_license_complete_tier/read_rules.ts | 14 ++-- .../read_rules_ess.ts | 6 +- .../update_rules.ts | 13 ++-- .../update_rules_bulk.ts | 27 ++++---- .../update_rules.ts | 30 ++++---- .../update_rules_bulk.ts | 66 +++++++----------- .../update_rules_ess.ts | 5 +- .../items/create_exception_list_items.ts | 11 ++- .../items/delete_exception_list_items.ts | 7 +- .../items/find_exception_list_items.ts | 10 +-- .../items/read_exception_list_items.ts | 11 ++- .../items/update_exception_list_items.ts | 7 +- .../lists/create_exception_lists.ts | 7 +- .../lists/delete_exception_lists.ts | 7 +- .../lists/duplicate_exception_list.ts | 7 +- .../lists/find_exception_lists.ts | 5 +- .../lists/read_exception_lists.ts | 9 ++- .../lists/update_exception_lists.ts | 9 ++- .../items/create_list_items.ts | 16 +++-- .../items/delete_list_items.ts | 7 +- .../items/import_list_items.ts | 7 +- .../items/import_list_items_migrations.ts | 5 +- .../items/patch_list_items.ts | 7 +- .../items/read_list_items.ts | 7 +- .../items/update_list_items.ts | 7 +- .../lists/create_lists.ts | 7 +- .../lists/delete_lists.ts | 11 ++- .../lists/find_lists.ts | 5 +- .../lists/find_lists_by_size.ts | 9 +-- .../lists/patch_lists.ts | 9 ++- .../lists/read_lists.ts | 7 +- .../lists/update_lists.ts | 9 ++- 63 files changed, 464 insertions(+), 366 deletions(-) create mode 100644 x-pack/test/security_solution_api_integration/config/services/security_solution_ess_utils.ts create mode 100644 x-pack/test/security_solution_api_integration/config/services/security_solution_serverless_supertest.ts create mode 100644 x-pack/test/security_solution_api_integration/config/services/security_solution_serverless_utils.ts create mode 100644 x-pack/test/security_solution_api_integration/config/services/types.ts diff --git a/x-pack/test/security_solution_api_integration/README.md b/x-pack/test/security_solution_api_integration/README.md index eeb0682c1358e..450558737b1e9 100644 --- a/x-pack/test/security_solution_api_integration/README.md +++ b/x-pack/test/security_solution_api_integration/README.md @@ -111,7 +111,43 @@ In this project, you can run various commands to execute tests and workflows, ea ```shell npm run initialize-server:dr:default exceptions/workflows ess ``` - 5. **Run tests for "exception_workflows" using the ess runner in the "essEnv" environment:** + 5. **Run tests for "exception_workflows" using the ess runner in the "essEnv" environment:** ```shell npm run run-tests:dr:default exceptions/workflows ess essEnv - ``` \ No newline at end of file + ``` + +## Testing with serverless roles + +The `supertest` service is logged with the `admin` role by default on serverless. Ideally, every test that runs on serverless should use the most appropriate role. + +The `securitySolutionUtils` helper exports the `createSuperTest` function, which accepts the role as a parameter. +You need to call `createSuperTest` from a lifecycle hook and wait for it to return the `supertest` instance. +All API calls using the returned instance will inject the required auth headers. + +**On ESS, `createSuperTest` returns a basic `supertest` instance without headers.* + +```js +import TestAgent from 'supertest/lib/agent'; + +export default ({ getService }: FtrProviderContext) => { + const utils = getService('securitySolutionUtils'); + + describe('@ess @serverless my_test', () => { + let supertest: TestAgent; + + before(async () => { + supertest = await utils.createSuperTest('admin'); + }); + ... +``` + +If you need to use multiple roles in a single test, you can instantiate multiple `supertest` versions. +```js +before(async () => { + adminSupertest = await utils.createSuperTest('admin'); + viewerSupertest = await utils.createSuperTest('viewer'); +}); +... +``` + +The helper keeps track of only one active session per role. So, if you instantiate `supertest` twice for the same role, the first instance will have an invalid API key. diff --git a/x-pack/test/security_solution_api_integration/config/ess/config.base.ts b/x-pack/test/security_solution_api_integration/config/ess/config.base.ts index 0fbe6b12a7ade..7256432174e3c 100644 --- a/x-pack/test/security_solution_api_integration/config/ess/config.base.ts +++ b/x-pack/test/security_solution_api_integration/config/ess/config.base.ts @@ -7,7 +7,7 @@ import { CA_CERT_PATH } from '@kbn/dev-utils'; import { FtrConfigProviderContext, kbnTestConfig, kibanaTestUser } from '@kbn/test'; -import { services } from '../../../api_integration/services'; +import { services } from './services'; import { PRECONFIGURED_ACTION_CONNECTORS } from '../shared'; interface CreateTestConfigOptions { diff --git a/x-pack/test/security_solution_api_integration/config/ess/services.ts b/x-pack/test/security_solution_api_integration/config/ess/services.ts index d6a3c415f29df..e5f66d5c1928a 100644 --- a/x-pack/test/security_solution_api_integration/config/ess/services.ts +++ b/x-pack/test/security_solution_api_integration/config/ess/services.ts @@ -7,8 +7,10 @@ import { SpacesServiceProvider } from '../../../common/services/spaces'; import { services as essServices } from '../../../api_integration/services'; +import { SecuritySolutionESSUtils } from '../services/security_solution_ess_utils'; export const services = { ...essServices, spaces: SpacesServiceProvider, + securitySolutionUtils: SecuritySolutionESSUtils, }; diff --git a/x-pack/test/security_solution_api_integration/config/serverless/config.base.essentials.ts b/x-pack/test/security_solution_api_integration/config/serverless/config.base.essentials.ts index 55a7957ae20d6..3b4a220a1c0bc 100644 --- a/x-pack/test/security_solution_api_integration/config/serverless/config.base.essentials.ts +++ b/x-pack/test/security_solution_api_integration/config/serverless/config.base.essentials.ts @@ -11,7 +11,7 @@ export interface CreateTestConfigOptions { kbnTestServerArgs?: string[]; kbnTestServerEnv?: Record; } -import { services } from '../../../../test_serverless/api_integration/services'; +import { services } from './services'; export function createTestConfig(options: CreateTestConfigOptions) { return async ({ readConfigFile }: FtrConfigProviderContext) => { diff --git a/x-pack/test/security_solution_api_integration/config/serverless/services.ts b/x-pack/test/security_solution_api_integration/config/serverless/services.ts index c033d11d1d2a4..c57007f774541 100644 --- a/x-pack/test/security_solution_api_integration/config/serverless/services.ts +++ b/x-pack/test/security_solution_api_integration/config/serverless/services.ts @@ -8,9 +8,13 @@ import { SpacesServiceProvider } from '../../../common/services/spaces'; import { BsearchSecureService } from '../../../../test_serverless/shared/services/bsearch_secure'; import { services as serverlessServices } from '../../../../test_serverless/api_integration/services'; +import { SecuritySolutionServerlessUtils } from '../services/security_solution_serverless_utils'; +import { SecuritySolutionServerlessSuperTest } from '../services/security_solution_serverless_supertest'; export const services = { ...serverlessServices, spaces: SpacesServiceProvider, secureBsearch: BsearchSecureService, + securitySolutionUtils: SecuritySolutionServerlessUtils, + supertest: SecuritySolutionServerlessSuperTest, }; diff --git a/x-pack/test/security_solution_api_integration/config/services/security_solution_ess_utils.ts b/x-pack/test/security_solution_api_integration/config/services/security_solution_ess_utils.ts new file mode 100644 index 0000000000000..4a69d1db5e253 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/config/services/security_solution_ess_utils.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 { FtrProviderContext } from '../../ftr_provider_context'; +import { SecuritySolutionUtils } from './types'; + +export function SecuritySolutionESSUtils({ + getService, +}: FtrProviderContext): SecuritySolutionUtils { + const config = getService('config'); + const supertest = getService('supertest'); + + return { + getUsername: (_role?: string) => + Promise.resolve(config.get('servers.kibana.username') as string), + createSuperTest: (_role?: string) => Promise.resolve(supertest), + }; +} diff --git a/x-pack/test/security_solution_api_integration/config/services/security_solution_serverless_supertest.ts b/x-pack/test/security_solution_api_integration/config/services/security_solution_serverless_supertest.ts new file mode 100644 index 0000000000000..8341396ee3c2d --- /dev/null +++ b/x-pack/test/security_solution_api_integration/config/services/security_solution_serverless_supertest.ts @@ -0,0 +1,15 @@ +/* + * 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 { FtrProviderContext } from '../../ftr_provider_context'; + +// It is wrapper around supertest that injects Serverless auth headers for the admin user. +export async function SecuritySolutionServerlessSuperTest({ getService }: FtrProviderContext) { + const { createSuperTest } = getService('securitySolutionUtils'); + + return await createSuperTest('admin'); +} diff --git a/x-pack/test/security_solution_api_integration/config/services/security_solution_serverless_utils.ts b/x-pack/test/security_solution_api_integration/config/services/security_solution_serverless_utils.ts new file mode 100644 index 0000000000000..6af51abccc79c --- /dev/null +++ b/x-pack/test/security_solution_api_integration/config/services/security_solution_serverless_utils.ts @@ -0,0 +1,68 @@ +/* + * 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 supertest from 'supertest'; +import { format as formatUrl } from 'url'; +import { RoleCredentials } from '../../../../test_serverless/shared/services'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { SecuritySolutionUtils } from './types'; + +export function SecuritySolutionServerlessUtils({ + getService, +}: FtrProviderContext): SecuritySolutionUtils { + const svlUserManager = getService('svlUserManager'); + const lifecycle = getService('lifecycle'); + const svlCommonApi = getService('svlCommonApi'); + const config = getService('config'); + const log = getService('log'); + + const rolesCredentials = new Map(); + const commonRequestHeader = svlCommonApi.getCommonRequestHeader(); + const kbnUrl = formatUrl({ + ...config.get('servers.kibana'), + auth: false, + }); + const agentWithCommonHeaders = supertest.agent(kbnUrl).set(commonRequestHeader); + + async function invalidateApiKey(credentials: RoleCredentials) { + await svlUserManager.invalidateApiKeyForRole(credentials); + } + + async function cleanCredentials(role: string) { + if (rolesCredentials.has(role)) { + log.debug(`Invalidating API key for role [${role}]`); + await invalidateApiKey(rolesCredentials.get(role)!); + rolesCredentials.delete(role); + } + } + + // Invalidate API keys when all tests have finished. + lifecycle.cleanup.add(async () => { + rolesCredentials.forEach((credential, role) => { + log.debug(`Invalidating API key for role [${role}]`); + invalidateApiKey(credential); + }); + }); + + return { + getUsername: async (role = 'admin') => { + const { username } = await svlUserManager.getUserData(role); + + return username; + }, + /** + * Only one API key for each role can be active at a time. + */ + createSuperTest: async (role = 'admin') => { + cleanCredentials(role); + const credentials = await svlUserManager.createApiKeyForRole(role); + rolesCredentials.set(role, credentials); + + return agentWithCommonHeaders.set(credentials.apiKeyHeader); + }, + }; +} diff --git a/x-pack/test/security_solution_api_integration/config/services/types.ts b/x-pack/test/security_solution_api_integration/config/services/types.ts new file mode 100644 index 0000000000000..b0a22e8f3a12e --- /dev/null +++ b/x-pack/test/security_solution_api_integration/config/services/types.ts @@ -0,0 +1,13 @@ +/* + * 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 TestAgent from 'supertest/lib/agent'; + +export interface SecuritySolutionUtils { + getUsername: (role?: string) => Promise; + createSuperTest: (role?: string) => Promise>; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/create_rule_exceptions.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/create_rule_exceptions.ts index 21147663a630d..8b13aa64ac6b2 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/create_rule_exceptions.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/exceptions/workflows/basic_license_essentials_tier/create_rule_exceptions.ts @@ -45,8 +45,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@serverless @serverlessQA @ess create "rule_default" exceptions', () => { before(async () => { @@ -61,7 +60,7 @@ export default ({ getService }: FtrProviderContext) => { it('creates and associates a `rule_default` exception list to a rule if one not already found', async () => { const rule = await createRule(supertest, log, getSimpleRule('rule-2')); - + const username = await utils.getUsername(); const { body: items } = await supertest .post(`${DETECTION_ENGINE_RULES_URL}/${rule.id}/exceptions`) .set('kbn-xsrf', 'true') @@ -82,7 +81,7 @@ export default ({ getService }: FtrProviderContext) => { expect(itemsWithoutServerGeneratedValues).to.eql([ { comments: [], - created_by: ELASTICSEARCH_USERNAME, + created_by: username, description: 'Exception item for rule default exception list', entries: [ { @@ -98,13 +97,14 @@ export default ({ getService }: FtrProviderContext) => { os_types: [], tags: [], type: 'simple', - updated_by: ELASTICSEARCH_USERNAME, + updated_by: username, }, ]); expect(udpatedRule.exceptions_list.some((list) => list.type === 'rule_default')).to.eql(true); }); it('creates and associates a `rule_default` exception list to a rule even when rule has non existent default list attached', async () => { + const username = await utils.getUsername(); // create a rule that has a non existent default exception list const rule = await createRule(supertest, log, { ...getSimpleRule('rule-5'), @@ -146,7 +146,7 @@ export default ({ getService }: FtrProviderContext) => { expect(itemsWithoutServerGeneratedValues).to.eql([ { comments: [], - created_by: ELASTICSEARCH_USERNAME, + created_by: username, description: 'Exception item for rule default exception list', entries: [ { @@ -162,12 +162,13 @@ export default ({ getService }: FtrProviderContext) => { os_types: [], tags: [], type: 'simple', - updated_by: ELASTICSEARCH_USERNAME, + updated_by: username, }, ]); }); it('adds exception items to rule default exception list', async () => { + const username = await utils.getUsername(); // create default exception list const exceptionList: CreateExceptionListSchema = { ...getCreateExceptionListMinimalSchemaMock(), @@ -208,7 +209,7 @@ export default ({ getService }: FtrProviderContext) => { ); expect(itemsWithoutServerGeneratedValues[0]).to.eql({ comments: [], - created_by: ELASTICSEARCH_USERNAME, + created_by: username, description: 'Exception item for rule default exception list', entries: [ { @@ -224,7 +225,7 @@ export default ({ getService }: FtrProviderContext) => { os_types: [], tags: [], type: 'simple', - updated_by: ELASTICSEARCH_USERNAME, + updated_by: username, }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/esql.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/esql.ts index 1bdf089844746..cbc7f43cfe6cc 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/esql.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/esql.ts @@ -37,8 +37,7 @@ export default ({ getService }: FtrProviderContext) => { const es = getService('es'); const log = getService('log'); const kibanaServer = getService('kibanaServer'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); const { indexEnhancedDocuments, indexListOfDocuments, indexGeneratedDocuments } = dataGeneratorFactory({ @@ -66,6 +65,7 @@ export default ({ getService }: FtrProviderContext) => { // First test creates a real rule - remaining tests use preview API it('should generate 1 alert with during actual rule execution', async () => { const id = uuidv4(); + const username = await utils.getUsername(); const interval: [string, string] = ['2020-10-28T06:00:00.000Z', '2020-10-28T06:10:00.000Z']; const doc1 = { agent: { name: 'test-1' } }; const doc2 = { agent: { name: 'test-2' } }; @@ -140,7 +140,7 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.risk_score': 55, 'kibana.alert.rule.actions': [], 'kibana.alert.rule.author': [], - 'kibana.alert.rule.created_by': ELASTICSEARCH_USERNAME, + 'kibana.alert.rule.created_by': username, 'kibana.alert.rule.description': 'Detecting root and admin users', 'kibana.alert.rule.enabled': true, 'kibana.alert.rule.exceptions_list': [], @@ -157,7 +157,7 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.rule.threat': [], 'kibana.alert.rule.to': 'now', 'kibana.alert.rule.type': 'esql', - 'kibana.alert.rule.updated_by': ELASTICSEARCH_USERNAME, + 'kibana.alert.rule.updated_by': username, 'kibana.alert.rule.version': 1, 'kibana.alert.workflow_tags': [], 'kibana.alert.workflow_assignee_ids': [], diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/indicator_match.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/indicator_match.ts index a999b430a521a..81b41ee1b0d5f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/indicator_match.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/indicator_match.ts @@ -158,7 +158,7 @@ export default ({ getService }: FtrProviderContext) => { // TODO: add a new service for loading archiver files similar to "getService('es')" const config = getService('config'); const isServerless = config.get('serverless'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); const dataPathBuilder = new EsArchivePathBuilder(isServerless); const audibeatHostsPath = dataPathBuilder.getPath('auditbeat/hosts'); const threatIntelPath = dataPathBuilder.getPath('filebeat/threat_intel'); @@ -186,6 +186,7 @@ export default ({ getService }: FtrProviderContext) => { // First 2 test creates a real rule - remaining tests use preview API it('should be able to execute and get all alerts when doing a specific query (terms query)', async () => { + const username = await utils.getUsername(); const rule: ThreatMatchRuleCreateProps = createThreatMatchRule(); const createdRule = await createRule(supertest, log, rule); @@ -320,7 +321,7 @@ export default ({ getService }: FtrProviderContext) => { author: [], category: 'Indicator Match Rule', consumer: 'siem', - created_by: ELASTICSEARCH_USERNAME, + created_by: username, description: 'Detecting root and admin users', enabled: true, exceptions_list: [], @@ -342,13 +343,14 @@ export default ({ getService }: FtrProviderContext) => { to: 'now', type: 'threat_match', updated_at: fullAlert[ALERT_RULE_UPDATED_AT], - updated_by: ELASTICSEARCH_USERNAME, + updated_by: username, uuid: fullAlert[ALERT_RULE_UUID], version: 1, }), }); }); it('should be able to execute and get all alerts when doing a specific query (match query)', async () => { + const username = await utils.getUsername(); const rule: ThreatMatchRuleCreateProps = createThreatMatchRule({ threat_mapping: [ // We match host.name against host.name @@ -499,7 +501,7 @@ export default ({ getService }: FtrProviderContext) => { author: [], category: 'Indicator Match Rule', consumer: 'siem', - created_by: ELASTICSEARCH_USERNAME, + created_by: username, description: 'Detecting root and admin users', enabled: true, exceptions_list: [], @@ -521,7 +523,7 @@ export default ({ getService }: FtrProviderContext) => { to: 'now', type: 'threat_match', updated_at: fullAlert[ALERT_RULE_UPDATED_AT], - updated_by: ELASTICSEARCH_USERNAME, + updated_by: username, uuid: fullAlert[ALERT_RULE_UUID], version: 1, }), diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/new_terms.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/new_terms.ts index 9e2638981a9e8..ec0602290b935 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/new_terms.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/detection_engine/rule_execution_logic/trial_license_complete_tier/execution_logic/new_terms.ts @@ -46,8 +46,8 @@ export default ({ getService }: FtrProviderContext) => { log, }); // TODO: add a new service for loading archiver files similar to "getService('es')" + const utils = getService('securitySolutionUtils'); const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); const isServerless = config.get('serverless'); const dataPathBuilder = new EsArchivePathBuilder(isServerless); const path = dataPathBuilder.getPath('auditbeat/hosts'); @@ -99,6 +99,7 @@ export default ({ getService }: FtrProviderContext) => { // suricata-sensor-san-francisco appears in a document at 2019-02-19T20:42:08.230Z, but also appears // in earlier documents so is not new. An alert should not be generated for that term. it('should generate 1 alert with 1 selected field', async () => { + const username = await utils.getUsername(); const rule: NewTermsRuleCreateProps = { ...getCreateNewTermsRulesSchemaMock('rule-1', true), new_terms_fields: ['host.name'], @@ -214,7 +215,7 @@ export default ({ getService }: FtrProviderContext) => { }, 'kibana.alert.rule.actions': [], 'kibana.alert.rule.author': [], - 'kibana.alert.rule.created_by': ELASTICSEARCH_USERNAME, + 'kibana.alert.rule.created_by': username, 'kibana.alert.rule.description': 'Detecting root and admin users', 'kibana.alert.rule.enabled': true, 'kibana.alert.rule.exceptions_list': [], @@ -232,7 +233,7 @@ export default ({ getService }: FtrProviderContext) => { 'kibana.alert.rule.threat': [], 'kibana.alert.rule.to': 'now', 'kibana.alert.rule.type': 'new_terms', - 'kibana.alert.rule.updated_by': ELASTICSEARCH_USERNAME, + 'kibana.alert.rule.updated_by': username, 'kibana.alert.rule.version': 1, 'kibana.alert.rule.risk_score': 55, 'kibana.alert.rule.severity': 'high', diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts index 091707df88d0a..8a1bd6cf4ecfd 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_bulk_actions/trial_license_complete_tier/perform_bulk_action.ts @@ -48,9 +48,7 @@ export default ({ getService }: FtrProviderContext): void => { const es = getService('es'); const log = getService('log'); const esArchiver = getService('esArchiver'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); const postBulkAction = () => supertest @@ -218,7 +216,7 @@ export default ({ getService }: FtrProviderContext): void => { const [ruleJson, connectorsJson, exportDetailsJson] = body.toString().split(/\n/); const rule = removeServerGeneratedProperties(JSON.parse(ruleJson)); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(rule).toEqual({ ...expectedRule, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_ml_rules_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_ml_rules_privileges.ts index fe89747eaa375..a8c70f1518f92 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_ml_rules_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_ml_rules_privileges.ts @@ -25,9 +25,9 @@ export default ({ getService }: FtrProviderContext) => { const es = getService('es'); // TODO: add a new service for loading archiver files similar to "getService('es')" const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); const isServerless = config.get('serverless'); const dataPathBuilder = new EsArchivePathBuilder(isServerless); + const utils = getService('securitySolutionUtils'); const auditbeatPath = dataPathBuilder.getPath('auditbeat/hosts'); describe('create_ml_rules', () => { @@ -72,7 +72,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleMlRule(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleMlRule(), await utils.getUsername()); expect(bodyToCompare).toEqual(expect.objectContaining(expectedRule)); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules.ts index 2f5ffd07e7d00..5bad760d3f91c 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules.ts @@ -32,9 +32,9 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); + const utils = getService('securitySolutionUtils'); // TODO: add a new service for loading archiver files similar to "getService('es')" const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); const isServerless = config.get('serverless'); const dataPathBuilder = new EsArchivePathBuilder(isServerless); const auditbeatPath = dataPathBuilder.getPath('auditbeat/hosts'); @@ -64,7 +64,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).toEqual(expectedRule); }); @@ -159,7 +159,7 @@ export default ({ getService }: FtrProviderContext) => { version: 1, revision: 0, }, - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).toEqual(expectedRule); @@ -173,7 +173,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).toEqual(expectedRule); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules_bulk.ts index 4356c8b82b8b4..529c3615e9e8e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/basic_license_essentials_tier/create_rules_bulk.ts @@ -33,10 +33,10 @@ export default ({ getService }: FtrProviderContext): void => { const es = getService('es'); // TODO: add a new service for loading archiver files similar to "getService('es')" const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); const isServerless = config.get('serverless'); const dataPathBuilder = new EsArchivePathBuilder(isServerless); const auditbeatPath = dataPathBuilder.getPath('auditbeat/hosts'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless create_rules_bulk', () => { describe('creating rules in bulk', () => { @@ -63,7 +63,7 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body[0]); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).toEqual(expectedRule); }); @@ -114,7 +114,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).toEqual(expectedRule); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/trial_license_complete_tier/create_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/trial_license_complete_tier/create_rules.ts index e6e4e4697d099..c3bdc9b4661d4 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/trial_license_complete_tier/create_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_creation/trial_license_complete_tier/create_rules.ts @@ -48,9 +48,7 @@ export default ({ getService }: FtrProviderContext) => { const supertestWithoutAuth = getService('supertestWithoutAuth'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@serverless @ess create_rules', () => { describe('rule creation', () => { @@ -75,6 +73,7 @@ export default ({ getService }: FtrProviderContext) => { describe('elastic admin', () => { it('creates a custom query rule', async () => { + const username = await utils.getUsername(); const { body } = await securitySolutionApi .createRule({ body: getCustomQueryRuleParams() }) .expect(200); @@ -82,13 +81,14 @@ export default ({ getService }: FtrProviderContext) => { expect(body).toEqual( expect.objectContaining({ ...getCustomQueryRuleParams(), - created_by: ELASTICSEARCH_USERNAME, - updated_by: ELASTICSEARCH_USERNAME, + created_by: username, + updated_by: username, }) ); }); it('creates a saved query rule', async () => { + const username = await utils.getUsername(); const savedQueryRuleParams = getSavedQueryRuleParams({ data_view_id: 'my-data-view', type: 'saved_query', @@ -102,8 +102,8 @@ export default ({ getService }: FtrProviderContext) => { expect(body).toEqual( expect.objectContaining({ ...savedQueryRuleParams, - created_by: ELASTICSEARCH_USERNAME, - updated_by: ELASTICSEARCH_USERNAME, + created_by: username, + updated_by: username, }) ); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/delete_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/delete_rules.ts index f7dd02061f429..75e3be0d825ee 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/delete_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/delete_rules.ts @@ -29,8 +29,7 @@ export default ({ getService }: FtrProviderContext): void => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless delete_rules', () => { describe('deleting rules', () => { @@ -52,7 +51,7 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -68,7 +67,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -85,7 +84,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/delete_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/delete_rules_bulk.ts index 0a3c419b6f1c4..bfde40d8b0db7 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/delete_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/basic_license_essentials_tier/delete_rules_bulk.ts @@ -30,8 +30,7 @@ export default ({ getService }: FtrProviderContext): void => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless delete_rules_bulk', () => { describe('deleting rules bulk using DELETE', () => { @@ -53,7 +52,7 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body[0]); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -69,7 +68,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -86,7 +85,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -136,7 +135,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect([bodyToCompare, body[1]]).to.eql([ @@ -175,7 +174,7 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body[0]); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -194,7 +193,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -214,7 +213,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -271,7 +270,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect([bodyToCompare, body[1]]).to.eql([ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/delete_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/delete_rules.ts index a4161baa54547..4e2628f196c22 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/delete_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/delete_rules.ts @@ -29,9 +29,7 @@ export default ({ getService }: FtrProviderContext): void => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless delete_rules', () => { describe('deleting rules', () => { @@ -53,7 +51,7 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -69,7 +67,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -86,7 +84,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/delete_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/delete_rules_bulk.ts index cd4deb8cff7d8..361dfbef8c642 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/delete_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_delete/trial_license_complete_tier/delete_rules_bulk.ts @@ -35,9 +35,7 @@ export default ({ getService }: FtrProviderContext): void => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); // See https://github.com/elastic/kibana/issues/130963 for discussion on deprecation describe('@ess @skipInServerlesMKI delete_rules_bulk', () => { @@ -74,7 +72,7 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body[0]); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -90,7 +88,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -107,7 +105,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -157,7 +155,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect([bodyToCompare, body[1]]).to.eql([ @@ -196,7 +194,7 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body[0]); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -214,7 +212,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -235,7 +233,7 @@ export default ({ getService }: FtrProviderContext): void => { const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -292,7 +290,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect([bodyToCompare, body[1]]).to.eql([ expectedRule, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules.ts index a2658ed2fb285..475446b90d905 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules.ts @@ -29,8 +29,7 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless patch_rules', () => { describe('patch rules', () => { @@ -54,7 +53,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); @@ -128,7 +127,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutputWithoutRuleId(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); expect(bodyToCompare).toEqual(expectedRule); @@ -145,7 +144,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); @@ -161,7 +160,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.enabled = false; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); @@ -179,7 +178,7 @@ export default ({ getService }: FtrProviderContext) => { outputRule.enabled = false; outputRule.severity = 'low'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); @@ -205,7 +204,7 @@ export default ({ getService }: FtrProviderContext) => { outputRule.timeline_title = 'some title'; outputRule.timeline_id = 'some id'; outputRule.revision = 2; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules_bulk.ts index a04245eac5517..207456d48f430 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/basic_license_essentials_tier/patch_rules_bulk.ts @@ -29,8 +29,7 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless patch_rules_bulk', () => { describe('patch rules bulk', () => { @@ -55,7 +54,7 @@ export default ({ getService }: FtrProviderContext) => { outputRule.name = 'some other name'; outputRule.revision = 1; const bodyToCompare = removeServerGeneratedProperties(body[0]); - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); expect(bodyToCompare).toEqual(expectedRule); }); @@ -104,6 +103,7 @@ export default ({ getService }: FtrProviderContext) => { it('should patch two rule properties of name using the two rules rule_id', async () => { await createRule(supertest, log, getSimpleRule('rule-1')); await createRule(supertest, log, getSimpleRule('rule-2')); + const username = await utils.getUsername(); // patch both rule names const { body } = await securitySolutionApi @@ -118,12 +118,12 @@ export default ({ getService }: FtrProviderContext) => { const outputRule1 = getSimpleRuleOutput(); outputRule1.name = 'some other name'; outputRule1.revision = 1; - const expectedRule1 = updateUsername(outputRule1, ELASTICSEARCH_USERNAME); + const expectedRule1 = updateUsername(outputRule1, username); const outputRule2 = getSimpleRuleOutput('rule-2'); outputRule2.name = 'some other name'; outputRule2.revision = 1; - const expectedRule2 = updateUsername(outputRule2, ELASTICSEARCH_USERNAME); + const expectedRule2 = updateUsername(outputRule2, username); const bodyToCompare1 = removeServerGeneratedProperties(body[0]); const bodyToCompare2 = removeServerGeneratedProperties(body[1]); @@ -142,7 +142,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); }); @@ -150,6 +150,7 @@ export default ({ getService }: FtrProviderContext) => { it('should patch two rule properties of name using the two rules id', async () => { const createRule1 = await createRule(supertest, log, getSimpleRule('rule-1')); const createRule2 = await createRule(supertest, log, getSimpleRule('rule-2')); + const username = await utils.getUsername(); // patch both rule names const { body } = await securitySolutionApi @@ -164,12 +165,12 @@ export default ({ getService }: FtrProviderContext) => { const outputRule1 = getSimpleRuleOutputWithoutRuleId('rule-1'); outputRule1.name = 'some other name'; outputRule1.revision = 1; - const expectedRule = updateUsername(outputRule1, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule1, username); const outputRule2 = getSimpleRuleOutputWithoutRuleId('rule-2'); outputRule2.name = 'some other name'; outputRule2.revision = 1; - const expectedRule2 = updateUsername(outputRule2, ELASTICSEARCH_USERNAME); + const expectedRule2 = updateUsername(outputRule2, username); const bodyToCompare1 = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const bodyToCompare2 = removeServerGeneratedPropertiesIncludingRuleId(body[1]); @@ -188,7 +189,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -204,7 +205,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.enabled = false; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -222,7 +223,7 @@ export default ({ getService }: FtrProviderContext) => { outputRule.enabled = false; outputRule.severity = 'low'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -248,7 +249,7 @@ export default ({ getService }: FtrProviderContext) => { outputRule.timeline_title = 'some title'; outputRule.timeline_id = 'some id'; outputRule.revision = 2; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -301,7 +302,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect([bodyToCompare, body[1]]).toEqual([ @@ -332,7 +333,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect([bodyToCompare, body[1]]).toEqual([ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules.ts index 4a69f208c3bd5..a6a64857f6721 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules.ts @@ -43,9 +43,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless @skipInServerlessMKI patch_rules', () => { describe('patch rules', () => { @@ -69,7 +67,7 @@ export default ({ getService }: FtrProviderContext) => { .send({ rule_id: 'rule-1', name: 'some other name' }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -88,7 +86,7 @@ export default ({ getService }: FtrProviderContext) => { .send({ rule_id: 'rule-1', machine_learning_job_id: 'some_job_id' }) .expect(200); - const outputRule = updateUsername(getSimpleMlRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleMlRuleOutput(), await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).to.eql(outputRule); @@ -105,7 +103,7 @@ export default ({ getService }: FtrProviderContext) => { .send({ rule_id: 'rule-1', name: 'some other name' }) .expect(200); - const outputRule = updateUsername(getSimpleMlRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleMlRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -128,7 +126,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); outputRule.name = 'some other name'; @@ -147,7 +145,7 @@ export default ({ getService }: FtrProviderContext) => { .set('elastic-api-version', '2023-10-31') .send({ id: createdBody.id, name: 'some other name' }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -166,7 +164,7 @@ export default ({ getService }: FtrProviderContext) => { .send({ rule_id: 'rule-1', enabled: false }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.enabled = false; @@ -185,7 +183,7 @@ export default ({ getService }: FtrProviderContext) => { .send({ rule_id: 'rule-1', severity: 'low', enabled: false }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.enabled = false; outputRule.severity = 'low'; outputRule.revision = 1; @@ -213,7 +211,7 @@ export default ({ getService }: FtrProviderContext) => { .send({ rule_id: 'rule-1', name: 'some other name' }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.timeline_title = 'some title'; outputRule.timeline_id = 'some id'; @@ -436,7 +434,7 @@ export default ({ getService }: FtrProviderContext) => { ); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; @@ -466,7 +464,7 @@ export default ({ getService }: FtrProviderContext) => { ); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; @@ -505,7 +503,7 @@ export default ({ getService }: FtrProviderContext) => { const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; @@ -533,7 +531,7 @@ export default ({ getService }: FtrProviderContext) => { ); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; @@ -564,7 +562,7 @@ export default ({ getService }: FtrProviderContext) => { const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; expectedRule.actions = someActionsWithFrequencies.map((action) => ({ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules_bulk.ts index 88ca9c4ffe289..7e496ea73194d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules_bulk.ts @@ -39,9 +39,7 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); // See https://github.com/elastic/kibana/issues/130963 for discussion on deprecation describe('@ess @skipInServerless patch_rules_bulk', () => { @@ -81,7 +79,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkPatchRules({ body: [{ rule_id: 'rule-1', name: 'some other name' }] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -92,6 +90,7 @@ export default ({ getService }: FtrProviderContext) => { it('should patch two rule properties of name using the two rules rule_id', async () => { await createRule(supertest, log, getSimpleRule('rule-1')); await createRule(supertest, log, getSimpleRule('rule-2')); + const username = await utils.getUsername(); // patch both rule names const { body } = await securitySolutionApi @@ -103,12 +102,12 @@ export default ({ getService }: FtrProviderContext) => { }) .expect(200); - const outputRule1 = updateUsername(getSimpleRuleOutput('rule-1'), ELASTICSEARCH_USERNAME); + const outputRule1 = updateUsername(getSimpleRuleOutput('rule-1'), username); outputRule1.name = 'some other name'; outputRule1.revision = 1; - const outputRule2 = updateUsername(getSimpleRuleOutput('rule-2'), ELASTICSEARCH_USERNAME); + const outputRule2 = updateUsername(getSimpleRuleOutput('rule-2'), username); outputRule2.name = 'some other name'; outputRule2.revision = 1; @@ -127,7 +126,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkPatchRules({ body: [{ id: createRuleBody.id, name: 'some other name' }] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; const bodyToCompare = removeServerGeneratedProperties(body[0]); @@ -137,6 +136,7 @@ export default ({ getService }: FtrProviderContext) => { it('should patch two rule properties of name using the two rules id', async () => { const createRule1 = await createRule(supertest, log, getSimpleRule('rule-1')); const createRule2 = await createRule(supertest, log, getSimpleRule('rule-2')); + const username = await utils.getUsername(); // patch both rule names const { body } = await securitySolutionApi @@ -148,18 +148,12 @@ export default ({ getService }: FtrProviderContext) => { }) .expect(200); - const outputRule1 = updateUsername( - getSimpleRuleOutputWithoutRuleId('rule-1'), - ELASTICSEARCH_USERNAME - ); + const outputRule1 = updateUsername(getSimpleRuleOutputWithoutRuleId('rule-1'), username); outputRule1.name = 'some other name'; outputRule1.revision = 1; - const outputRule2 = updateUsername( - getSimpleRuleOutputWithoutRuleId('rule-2'), - ELASTICSEARCH_USERNAME - ); + const outputRule2 = updateUsername(getSimpleRuleOutputWithoutRuleId('rule-2'), username); outputRule2.name = 'some other name'; outputRule2.revision = 1; @@ -210,13 +204,11 @@ export default ({ getService }: FtrProviderContext) => { const sidecarActionsPostResults = await getLegacyActionSO(es); expect(sidecarActionsPostResults.hits.hits.length).to.eql(0); + const username = await utils.getUsername(); // @ts-expect-error body.forEach((response) => { const bodyToCompare = removeServerGeneratedProperties(response); - const outputRule = updateUsername( - getSimpleRuleOutput(response.rule_id, false), - ELASTICSEARCH_USERNAME - ); + const outputRule = updateUsername(getSimpleRuleOutput(response.rule_id, false), username); outputRule.actions = [ { @@ -244,7 +236,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkPatchRules({ body: [{ id: createdBody.id, name: 'some other name' }] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; const bodyToCompare = removeServerGeneratedProperties(body[0]); @@ -259,7 +251,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkPatchRules({ body: [{ rule_id: 'rule-1', enabled: false }] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.enabled = false; @@ -275,7 +267,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkPatchRules({ body: [{ rule_id: 'rule-1', severity: 'low', enabled: false }] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.enabled = false; outputRule.severity = 'low'; @@ -300,7 +292,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkPatchRules({ body: [{ rule_id: 'rule-1', name: 'some other name' }] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.timeline_title = 'some title'; @@ -355,7 +347,7 @@ export default ({ getService }: FtrProviderContext) => { }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -386,7 +378,7 @@ export default ({ getService }: FtrProviderContext) => { }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules_ess.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules_ess.ts index 5efab4bb9e533..30398cd2cd1e9 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules_ess.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_patch/trial_license_complete_tier/patch_rules_ess.ts @@ -35,9 +35,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess patch_rules - ESS specific logic', () => { describe('patch rules', () => { @@ -80,7 +78,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(patchResponse.body); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.actions = [ { diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/find_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/find_rules.ts index 20da65ab16fdb..d21c78a68f5c4 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/find_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/find_rules.ts @@ -22,8 +22,7 @@ export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless find_rules', () => { beforeEach(async () => { @@ -48,7 +47,7 @@ export default ({ getService }: FtrProviderContext): void => { const { body } = await securitySolutionApi.findRules({ query: {} }).expect(200); body.data = [removeServerGeneratedProperties(body.data[0])]; - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(body).to.eql({ data: [expectedRule], @@ -66,7 +65,7 @@ export default ({ getService }: FtrProviderContext): void => { const { body } = await securitySolutionApi.findRules({ query: {} }).expect(200); body.data = [removeServerGeneratedProperties(body.data[0])]; - const expectedRule = updateUsername(getComplexRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getComplexRuleOutput(), await utils.getUsername()); expect(body).to.eql({ data: [expectedRule], page: 1, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/read_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/read_rules.ts index 35b45cc1faa46..21b31c702a7dc 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/read_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/basic_license_essentials_tier/read_rules.ts @@ -29,8 +29,7 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless read_rules', () => { describe('reading rules', () => { @@ -51,7 +50,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -64,7 +63,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -79,7 +78,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/find_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/find_rules.ts index fb9c9341a7529..2ef2890eeffa8 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/find_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/find_rules.ts @@ -23,9 +23,7 @@ export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless find_rules', () => { beforeEach(async () => { @@ -50,7 +48,7 @@ export default ({ getService }: FtrProviderContext): void => { const { body } = await securitySolutionApi.findRules({ query: {} }).expect(200); body.data = [removeServerGeneratedProperties(body.data[0])]; - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(body).to.eql({ data: [expectedRule], @@ -68,7 +66,7 @@ export default ({ getService }: FtrProviderContext): void => { const { body } = await securitySolutionApi.findRules({ query: {} }).expect(200); body.data = [removeServerGeneratedProperties(body.data[0])]; - const expectedRule = updateUsername(getComplexRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getComplexRuleOutput(), await utils.getUsername()); expect(body).to.eql({ data: [expectedRule], @@ -104,7 +102,7 @@ export default ({ getService }: FtrProviderContext): void => { // query the single rule from _find const { body } = await securitySolutionApi.findRules({ query: {} }).expect(200); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); const ruleWithActions: ReturnType = { ...expectedRule, actions: [ @@ -151,7 +149,7 @@ export default ({ getService }: FtrProviderContext): void => { // query the single rule from _find const { body } = await securitySolutionApi.findRules({ query: {} }).expect(200); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); const ruleWithActions: ReturnType = { ...expectedRule, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/find_rules_ess.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/find_rules_ess.ts index ccebf86486879..70d0758a390ec 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/find_rules_ess.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/find_rules_ess.ts @@ -32,9 +32,7 @@ export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess find_rules - ESS specific logic', () => { beforeEach(async () => { @@ -86,7 +84,7 @@ export default ({ getService }: FtrProviderContext): void => { .send() .expect(200); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); const ruleWithActions: ReturnType = { ...expectedRule, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/read_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/read_rules.ts index 2dc3e8168a24f..2e40bdb4d42a4 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/read_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/read_rules.ts @@ -29,9 +29,7 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless read_rules', () => { describe('reading rules', () => { @@ -52,7 +50,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -65,7 +63,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); expect(bodyToCompare).to.eql(expectedRule); }); @@ -80,7 +78,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expect(bodyToCompare).to.eql(expectedRule); @@ -135,7 +133,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); const ruleWithActions: ReturnType = { ...expectedRule, @@ -180,7 +178,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); const ruleWithActions: ReturnType = { ...expectedRule, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/read_rules_ess.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/read_rules_ess.ts index 78bbcadac71eb..1e6ccbdf0ef76 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/read_rules_ess.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_read/trial_license_complete_tier/read_rules_ess.ts @@ -35,9 +35,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess read_rules - ESS specific logic', () => { describe('reading rules', () => { @@ -97,7 +95,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeServerGeneratedProperties(body); - const expectedRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); const ruleWithActions: ReturnType = { ...expectedRule, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules.ts index 33505f9d150d6..06729d7ef31fa 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules.ts @@ -31,8 +31,7 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless update_rules', () => { describe('update rules', () => { @@ -59,7 +58,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); @@ -136,7 +135,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutputWithoutRuleId(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedPropertiesIncludingRuleId(body); expect(bodyToCompare).toEqual(expectedRule); @@ -156,7 +155,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); @@ -176,7 +175,7 @@ export default ({ getService }: FtrProviderContext) => { outputRule.enabled = false; outputRule.severity = 'low'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); @@ -201,7 +200,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 2; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body); expect(bodyToCompare).toEqual(expectedRule); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules_bulk.ts index effc64a241cc5..6708fe5a5e39d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/basic_license_essentials_tier/update_rules_bulk.ts @@ -30,8 +30,7 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless update_rules_bulk', () => { describe('update rules bulk', () => { @@ -58,7 +57,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -119,15 +118,16 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [updatedRule1, updatedRule2] }) .expect(200); + const username = await utils.getUsername(); const outputRule1 = getSimpleRuleOutput(); outputRule1.name = 'some other name'; outputRule1.revision = 1; - const expectedRule = updateUsername(outputRule1, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule1, username); const outputRule2 = getSimpleRuleOutput('rule-2'); outputRule2.name = 'some other name'; outputRule2.revision = 1; - const expectedRule2 = updateUsername(outputRule2, ELASTICSEARCH_USERNAME); + const expectedRule2 = updateUsername(outputRule2, username); const bodyToCompare1 = removeServerGeneratedProperties(body[0]); const bodyToCompare2 = removeServerGeneratedProperties(body[1]); @@ -151,7 +151,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -176,15 +176,16 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [updatedRule1, updatedRule2] }) .expect(200); + const username = await utils.getUsername(); const outputRule1 = getSimpleRuleOutputWithoutRuleId('rule-1'); outputRule1.name = 'some other name'; outputRule1.revision = 1; - const expectedRule = updateUsername(outputRule1, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule1, username); const outputRule2 = getSimpleRuleOutputWithoutRuleId('rule-2'); outputRule2.name = 'some other name'; outputRule2.revision = 1; - const expectedRule2 = updateUsername(outputRule2, ELASTICSEARCH_USERNAME); + const expectedRule2 = updateUsername(outputRule2, username); const bodyToCompare1 = removeServerGeneratedPropertiesIncludingRuleId(body[0]); const bodyToCompare2 = removeServerGeneratedPropertiesIncludingRuleId(body[1]); @@ -208,7 +209,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -230,7 +231,7 @@ export default ({ getService }: FtrProviderContext) => { outputRule.enabled = false; outputRule.severity = 'low'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -257,7 +258,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 2; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect(bodyToCompare).toEqual(expectedRule); @@ -319,7 +320,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect([bodyToCompare, body[1]]).toEqual([ @@ -355,7 +356,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = getSimpleRuleOutput(); outputRule.name = 'some other name'; outputRule.revision = 1; - const expectedRule = updateUsername(outputRule, ELASTICSEARCH_USERNAME); + const expectedRule = updateUsername(outputRule, await utils.getUsername()); const bodyToCompare = removeServerGeneratedProperties(body[0]); expect([bodyToCompare, body[1]]).toEqual([ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules.ts index 6d120a7944759..af9929f87832d 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules.ts @@ -46,9 +46,7 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless @skipInServerlessMKI update_rules', () => { describe('update rules', () => { @@ -72,7 +70,7 @@ export default ({ getService }: FtrProviderContext) => { const { body } = await securitySolutionApi.updateRule({ body: updatedRule }).expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -91,7 +89,7 @@ export default ({ getService }: FtrProviderContext) => { const { body } = await securitySolutionApi.updateRule({ body: updatedRule }).expect(200); - const outputRule = updateUsername(getSimpleMlRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleMlRuleOutput(), await utils.getUsername()); // @ts-expect-error type narrowing is lost due to Omit<> outputRule.machine_learning_job_id = ['legacy_job_id']; @@ -111,7 +109,7 @@ export default ({ getService }: FtrProviderContext) => { const { body } = await securitySolutionApi.updateRule({ body: updatedRule }).expect(200); - const outputRule = updateUsername(getSimpleMlRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleMlRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; const bodyToCompare = removeServerGeneratedProperties(body); @@ -133,7 +131,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); outputRule.name = 'some other name'; @@ -182,7 +180,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -203,7 +201,7 @@ export default ({ getService }: FtrProviderContext) => { const { body } = await securitySolutionApi.updateRule({ body: updatedRule }).expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -221,7 +219,7 @@ export default ({ getService }: FtrProviderContext) => { const { body } = await securitySolutionApi.updateRule({ body: updatedRule }).expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.enabled = false; outputRule.severity = 'low'; @@ -247,7 +245,7 @@ export default ({ getService }: FtrProviderContext) => { // update a simple rule's name const { body } = await securitySolutionApi.updateRule({ body: ruleUpdate2 }).expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), await utils.getUsername()); outputRule.name = 'some other name'; outputRule.revision = 2; @@ -579,7 +577,7 @@ export default ({ getService }: FtrProviderContext) => { ); const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; @@ -610,7 +608,7 @@ export default ({ getService }: FtrProviderContext) => { const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; expectedRule.actions = actionsWithoutFrequencies.map((action) => ({ @@ -648,7 +646,7 @@ export default ({ getService }: FtrProviderContext) => { const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; expectedRule.actions = actionsWithFrequencies; @@ -676,7 +674,7 @@ export default ({ getService }: FtrProviderContext) => { const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; expectedRule.actions = someActionsWithFrequencies.map((action) => ({ @@ -706,7 +704,7 @@ export default ({ getService }: FtrProviderContext) => { const expectedRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); expectedRule.revision = 1; expectedRule.actions = someActionsWithFrequencies.map((action) => ({ diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules_bulk.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules_bulk.ts index 2dead22fd358a..68886130e6cc3 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules_bulk.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules_bulk.ts @@ -49,12 +49,15 @@ export default ({ getService }: FtrProviderContext) => { const securitySolutionApi = getService('securitySolutionApi'); const log = getService('log'); const es = getService('es'); - // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); + let username: string; // See https://github.com/elastic/kibana/issues/130963 for discussion on deprecation describe('@ess update_rules_bulk', () => { + before(async () => { + username = await utils.getUsername(); + }); + describe('deprecations', () => { afterEach(async () => { await deleteAllRules(supertest, log); @@ -95,7 +98,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [updatedRule] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), username); outputRule.name = 'some other name'; outputRule.revision = 1; const bodyToCompare = removeServerGeneratedProperties(body[0]); @@ -119,11 +122,11 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [updatedRule1, updatedRule2] }) .expect(200); - const outputRule1 = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule1 = updateUsername(getSimpleRuleOutput(), username); outputRule1.name = 'some other name'; outputRule1.revision = 1; - const outputRule2 = updateUsername(getSimpleRuleOutput('rule-2'), ELASTICSEARCH_USERNAME); + const outputRule2 = updateUsername(getSimpleRuleOutput('rule-2'), username); outputRule2.name = 'some other name'; outputRule2.revision = 1; @@ -187,10 +190,7 @@ export default ({ getService }: FtrProviderContext) => { body.forEach((response) => { const bodyToCompare = removeServerGeneratedProperties(response); - const outputRule = updateUsername( - getSimpleRuleOutput(response.rule_id), - ELASTICSEARCH_USERNAME - ); + const outputRule = updateUsername(getSimpleRuleOutput(response.rule_id), username); outputRule.name = 'some other name'; outputRule.revision = 1; outputRule.actions = [ @@ -250,10 +250,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); body.forEach((response) => { - const outputRule = updateUsername( - getSimpleRuleOutput(response.rule_id), - ELASTICSEARCH_USERNAME - ); + const outputRule = updateUsername(getSimpleRuleOutput(response.rule_id), username); outputRule.name = 'some other name'; outputRule.revision = 1; outputRule.actions = []; @@ -275,7 +272,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [updatedRule1] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), username); outputRule.name = 'some other name'; outputRule.revision = 1; const bodyToCompare = removeServerGeneratedProperties(body[0]); @@ -301,11 +298,11 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [updatedRule1, updatedRule2] }) .expect(200); - const outputRule1 = updateUsername(getSimpleRuleOutput('rule-1'), ELASTICSEARCH_USERNAME); + const outputRule1 = updateUsername(getSimpleRuleOutput('rule-1'), username); outputRule1.name = 'some other name'; outputRule1.revision = 1; - const outputRule2 = updateUsername(getSimpleRuleOutput('rule-2'), ELASTICSEARCH_USERNAME); + const outputRule2 = updateUsername(getSimpleRuleOutput('rule-2'), username); outputRule2.name = 'some other name'; outputRule2.revision = 1; @@ -328,7 +325,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [updatedRule1] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), username); outputRule.name = 'some other name'; outputRule.revision = 1; const bodyToCompare = removeServerGeneratedProperties(body[0]); @@ -347,7 +344,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [updatedRule1] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), username); outputRule.enabled = false; outputRule.severity = 'low'; outputRule.revision = 1; @@ -374,7 +371,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [ruleUpdate2] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), username); outputRule.name = 'some other name'; outputRule.revision = 2; @@ -435,7 +432,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [ruleUpdate, ruleUpdate2] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), username); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -470,7 +467,7 @@ export default ({ getService }: FtrProviderContext) => { .bulkUpdateRules({ body: [rule1, rule2] }) .expect(200); - const outputRule = updateUsername(getSimpleRuleOutput(), ELASTICSEARCH_USERNAME); + const outputRule = updateUsername(getSimpleRuleOutput(), username); outputRule.name = 'some other name'; outputRule.revision = 1; @@ -629,10 +626,7 @@ export default ({ getService }: FtrProviderContext) => { actionsWithoutFrequencies ); - const expectedRule = updateUsername( - getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME - ); + const expectedRule = updateUsername(getSimpleRuleOutputWithoutRuleId(), username); expectedRule.revision = 1; expectedRule.actions = actionsWithoutFrequencies.map((action) => ({ ...action, @@ -660,10 +654,7 @@ export default ({ getService }: FtrProviderContext) => { actionsWithoutFrequencies ); - const expectedRule = updateUsername( - getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME - ); + const expectedRule = updateUsername(getSimpleRuleOutputWithoutRuleId(), username); expectedRule.revision = 1; expectedRule.actions = actionsWithoutFrequencies.map((action) => ({ ...action, @@ -698,10 +689,7 @@ export default ({ getService }: FtrProviderContext) => { actionsWithFrequencies ); - const expectedRule = updateUsername( - getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME - ); + const expectedRule = updateUsername(getSimpleRuleOutputWithoutRuleId(), username); expectedRule.revision = 1; expectedRule.actions = actionsWithFrequencies; @@ -726,10 +714,7 @@ export default ({ getService }: FtrProviderContext) => { someActionsWithFrequencies ); - const expectedRule = updateUsername( - getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME - ); + const expectedRule = updateUsername(getSimpleRuleOutputWithoutRuleId(), username); expectedRule.revision = 1; expectedRule.actions = someActionsWithFrequencies.map((action) => ({ ...action, @@ -756,10 +741,7 @@ export default ({ getService }: FtrProviderContext) => { someActionsWithFrequencies ); - const expectedRule = updateUsername( - getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME - ); + const expectedRule = updateUsername(getSimpleRuleOutputWithoutRuleId(), username); expectedRule.revision = 1; expectedRule.actions = someActionsWithFrequencies.map((action) => ({ ...action, diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules_ess.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules_ess.ts index b6c4862ccf298..4272345759f0e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules_ess.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/rules_management/rule_update/trial_license_complete_tier/update_rules_ess.ts @@ -37,8 +37,7 @@ export default ({ getService }: FtrProviderContext) => { const log = getService('log'); const es = getService('es'); // TODO: add a new service for pulling kibana username, similar to getService('es') - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess update_rules - ESS specific logic', () => { describe('update rules', () => { @@ -97,7 +96,7 @@ export default ({ getService }: FtrProviderContext) => { const outputRule = updateUsername( getSimpleRuleOutputWithoutRuleId(), - ELASTICSEARCH_USERNAME + await utils.getUsername() ); outputRule.name = 'some other name'; outputRule.revision = 1; diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/create_exception_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/create_exception_list_items.ts index ad7c413a3c6a7..b5a4dc3449eb1 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/create_exception_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/create_exception_list_items.ts @@ -26,8 +26,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless create_exception_list_items', () => { describe('validation errors', () => { @@ -65,7 +64,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -95,7 +94,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql({ - ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), entries, }); }); @@ -115,7 +114,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListItemServerGeneratedProperties(body); const outputList: Partial = { - ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), item_id: body.item_id, }; expect(bodyToCompare).to.eql(outputList); @@ -165,7 +164,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql({ - ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), expire_time: datetime, }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/delete_exception_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/delete_exception_list_items.ts index 4d3b2be7de27f..89ff41806c97f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/delete_exception_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/delete_exception_list_items.ts @@ -26,8 +26,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless delete_exception_list_items', () => { describe('delete exception list items', () => { @@ -62,7 +61,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -87,7 +86,7 @@ export default ({ getService }: FtrProviderContext) => { .set('kbn-xsrf', 'true') .expect(200); const outputtedList: Partial = { - ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), item_id: body.item_id, }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/find_exception_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/find_exception_list_items.ts index 3fcbd476b7547..bd9068d989c19 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/find_exception_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/find_exception_list_items.ts @@ -28,8 +28,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless find_exception_list_items', () => { describe('find exception list items', () => { @@ -105,11 +104,12 @@ export default ({ getService }: FtrProviderContext): void => { .expect(200); body.data = [removeExceptionListItemServerGeneratedProperties(body.data[0])]; + const username = await utils.getUsername(); expect(body).to.eql({ data: [ { comments: [], - created_by: ELASTICSEARCH_USERNAME, + created_by: username, description: 'some description', entries: [ { @@ -126,7 +126,7 @@ export default ({ getService }: FtrProviderContext): void => { os_types: ['windows'], tags: [], type: 'simple', - updated_by: ELASTICSEARCH_USERNAME, + updated_by: username, }, ], page: 1, @@ -177,7 +177,7 @@ export default ({ getService }: FtrProviderContext): void => { body.data = [removeExceptionListItemServerGeneratedProperties(body.data[0])]; expect(body).to.eql({ data: [ - getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), ], page: 1, per_page: 20, diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/read_exception_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/read_exception_list_items.ts index a2cffa490194c..d1689dcaf04b7 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/read_exception_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/read_exception_list_items.ts @@ -25,8 +25,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless read_exception_list_items', () => { describe('reading exception list items', () => { @@ -50,7 +49,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -76,7 +75,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -100,7 +99,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputtedList: Partial = { - ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), item_id: body.item_id, }; @@ -128,7 +127,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputtedList: Partial = { - ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), item_id: body.item_id, }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/update_exception_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/update_exception_list_items.ts index 6e0a1daa024e1..46766b1ace80f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/update_exception_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/items/update_exception_list_items.ts @@ -30,8 +30,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless update_exception_list_items', () => { describe('update exception list items', () => { @@ -253,7 +252,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', }; @@ -293,7 +292,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', item_id: body.item_id, }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/create_exception_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/create_exception_lists.ts index da066b078b0c4..0a1ecfa0b0d0a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/create_exception_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/create_exception_lists.ts @@ -21,8 +21,7 @@ import { deleteAllExceptions, removeExceptionListServerGeneratedProperties } fro export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless create_exception_lists', () => { describe('creating exception lists', () => { @@ -39,7 +38,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -52,7 +51,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListServerGeneratedProperties(body); const outputtedList: Partial = { - ...getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), list_id: bodyToCompare.list_id, }; expect(bodyToCompare).to.eql(outputtedList); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/delete_exception_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/delete_exception_lists.ts index ae109897fb138..98b387b1dc9bb 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/delete_exception_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/delete_exception_lists.ts @@ -22,8 +22,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless delete_exception_lists', () => { describe('delete exception lists', () => { @@ -49,7 +48,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -68,7 +67,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputtedList: Partial = { - ...getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), list_id: body.list_id, }; const bodyToCompare = removeExceptionListServerGeneratedProperties(body); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/duplicate_exception_list.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/duplicate_exception_list.ts index 14a4dcfb65ec7..927cf87b93d5a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/duplicate_exception_list.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/duplicate_exception_list.ts @@ -23,8 +23,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless duplicate_exception_lists', () => { afterEach(async () => { @@ -50,7 +49,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListServerGeneratedProperties(body); expect(bodyToCompare).to.eql({ - ...getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), type: 'detection', list_id: body.list_id, name: `${getCreateExceptionListDetectionSchemaMock().name} [Duplicate]`, @@ -91,7 +90,7 @@ export default ({ getService }: FtrProviderContext) => { const listBodyToCompare = removeExceptionListServerGeneratedProperties(listBody); expect(listBodyToCompare).to.eql({ - ...getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), type: 'detection', list_id: listBody.list_id, name: `${getCreateExceptionListDetectionSchemaMock().name} [Duplicate]`, diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/find_exception_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/find_exception_lists.ts index cb405b7b7d642..3ffcad93b568e 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/find_exception_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/find_exception_lists.ts @@ -17,8 +17,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless find_exception_lists', () => { describe('find exception lists', () => { @@ -58,7 +57,7 @@ export default ({ getService }: FtrProviderContext): void => { body.data = [removeExceptionListServerGeneratedProperties(body.data[0])]; expect(body).to.eql({ - data: [getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME)], + data: [getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername())], page: 1, per_page: 20, total: 1, diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/read_exception_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/read_exception_lists.ts index b2061928e1759..89239b1a93c25 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/read_exception_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/read_exception_lists.ts @@ -22,8 +22,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless read_exception_lists', () => { describe('reading exception lists', () => { @@ -46,7 +45,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -65,7 +64,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeExceptionListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -83,7 +82,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputtedList: Partial = { - ...getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), list_id: body.list_id, }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/update_exception_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/update_exception_lists.ts index 1a5aed16b128c..f399bcde87426 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/update_exception_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/exception_lists_items/trial_license_complete_tier/lists/update_exception_lists.ts @@ -23,8 +23,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless update_exception_lists', () => { describe('update exception lists', () => { @@ -53,7 +52,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', version: 2, }; @@ -86,7 +85,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', list_id: body.list_id, version: 2, @@ -118,7 +117,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getExceptionResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getExceptionResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', description: 'some other description', version: 2, diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/create_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/create_list_items.ts index f174fdff3f774..9ab6eb9361148 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/create_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/create_list_items.ts @@ -16,6 +16,7 @@ import { getCreateMinimalListItemSchemaMockWithoutId, } from '@kbn/lists-plugin/common/schemas/request/create_list_item_schema.mock'; import { getListItemResponseMockWithoutAutoGeneratedValues } from '@kbn/lists-plugin/common/schemas/response/list_item_schema.mock'; +import TestAgent from 'supertest/lib/agent'; import { createListsIndex, deleteListsIndex, @@ -25,12 +26,16 @@ import { import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { - const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless create_list_items', () => { + let supertest: TestAgent; + + before(async () => { + supertest = await utils.createSuperTest('admin'); + }); + describe('validation errors', () => { it('should give a 404 error that the list must exist first before being able to add a list item', async () => { const { body } = await supertest @@ -69,8 +74,9 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const bodyToCompare = removeListItemServerGeneratedProperties(body); + expect(bodyToCompare).to.eql( - getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -89,7 +95,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/delete_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/delete_list_items.ts index f17d950a10dc1..1f224e2e2db74 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/delete_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/delete_list_items.ts @@ -22,8 +22,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless delete_list_items', () => { describe('deleting list items', () => { @@ -58,7 +57,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -85,7 +84,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/import_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/import_list_items.ts index 7fabd749bc01d..3e2949568d7b9 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/import_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/import_list_items.ts @@ -24,8 +24,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless import_list_items', () => { describe('importing list items without an index', () => { @@ -106,7 +105,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeListServerGeneratedProperties(body); const outputtedList: Partial = { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'list_items.txt', description: 'File uploaded from file system of list_items.txt', }; @@ -139,7 +138,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeListItemServerGeneratedProperties(body[0]); const outputtedList: Partial = { - ...getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), list_id: 'list_items.txt', }; expect(bodyToCompare).to.eql(outputtedList); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/import_list_items_migrations.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/import_list_items_migrations.ts index cd614bd07e359..abcbc8499af86 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/import_list_items_migrations.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/import_list_items_migrations.ts @@ -22,8 +22,7 @@ export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const log = getService('log'); const es = getService('es'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess import_list_items_migrations', () => { describe('import list to legacy index and migrate it', () => { @@ -49,7 +48,7 @@ export default ({ getService }: FtrProviderContext): void => { const bodyToCompare = removeListServerGeneratedProperties(body); const outputtedList: Partial = { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'list_items.txt', description: 'File uploaded from file system of list_items.txt', }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/patch_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/patch_list_items.ts index 01a9d332ba355..ac25a46b458b8 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/patch_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/patch_list_items.ts @@ -29,8 +29,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); const retry = getService('retry'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless patch_list_items', () => { describe('patch list items', () => { @@ -70,7 +69,7 @@ export default ({ getService }: FtrProviderContext) => { .send(patchListItemPayload); const outputListItem: Partial = { - ...getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), value: '192.168.0.2', }; const bodyToCompare = removeListItemServerGeneratedProperties(body); @@ -120,7 +119,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputListItem: Partial = { - ...getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), value: '192.168.0.2', }; const bodyToCompare = { diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/read_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/read_list_items.ts index b0005ccb3fc0b..6b57358f68057 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/read_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/read_list_items.ts @@ -23,8 +23,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless read_list_items', () => { describe('reading list items', () => { @@ -56,7 +55,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -80,7 +79,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListItemServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/update_list_items.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/update_list_items.ts index 90d246d141866..073127cebfb3b 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/update_list_items.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/items/update_list_items.ts @@ -29,8 +29,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); const retry = getService('retry'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless update_list_items', () => { describe('update list items', () => { @@ -69,7 +68,7 @@ export default ({ getService }: FtrProviderContext) => { .send(updatedListItem); const outputListItem: Partial = { - ...getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), value: '192.168.0.2', }; const bodyToCompare = removeListItemServerGeneratedProperties(body); @@ -119,7 +118,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputListItem: Partial = { - ...getListItemResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListItemResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), value: '192.168.0.2', }; const bodyToCompare = { diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/create_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/create_lists.ts index 8cd7517c9efe8..d8ee7bcb7bd8a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/create_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/create_lists.ts @@ -25,8 +25,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless create_lists', () => { describe('creating lists', () => { @@ -47,7 +46,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -60,7 +59,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/delete_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/delete_lists.ts index 87b54d9a2e99a..bcb02e613defc 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/delete_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/delete_lists.ts @@ -33,8 +33,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless delete_lists', () => { describe('deleting lists', () => { @@ -62,7 +61,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -86,7 +85,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -106,7 +105,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -260,7 +259,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListServerGeneratedProperties(deleteListBody.body); expect(bodyToCompare).to.eql( - getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); await supertest diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/find_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/find_lists.ts index 3c47ad92eb824..f28f5252e3679 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/find_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/find_lists.ts @@ -22,8 +22,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless find_lists', () => { describe('find lists', () => { @@ -70,7 +69,7 @@ export default ({ getService }: FtrProviderContext): void => { // cursor is a constant changing value so we have to delete it as well. delete body.cursor; expect(body).to.eql({ - data: [getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME)], + data: [getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername())], page: 1, per_page: 20, total: 1, diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/find_lists_by_size.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/find_lists_by_size.ts index 813293ed1e7cc..f4aacaa2f8b77 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/find_lists_by_size.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/find_lists_by_size.ts @@ -25,8 +25,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext): void => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless find_lists_by_size', () => { describe('find lists by size', () => { @@ -81,11 +80,13 @@ export default ({ getService }: FtrProviderContext): void => { body.largeLists = [removeListServerGeneratedProperties(body.largeLists[0])]; // cursor is a constant changing value so we have to delete it as well. delete body.cursor; + + const username = await utils.getUsername(); expect(body).to.eql({ - smallLists: [getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME)], + smallLists: [getListResponseMockWithoutAutoGeneratedValues(username)], largeLists: [ { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(username), type: 'text', }, ], diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/patch_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/patch_lists.ts index 2586dcb23ab4f..51d9a2a9b5dab 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/patch_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/patch_lists.ts @@ -24,8 +24,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); const retry = getService('retry'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless patch_lists', () => { describe('patch lists', () => { @@ -59,7 +58,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', version: 2, }; @@ -100,7 +99,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', version: 2, }; @@ -140,7 +139,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', version: 2, }; diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/read_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/read_lists.ts index 025725fe01575..6750acd2f4a5a 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/read_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/read_lists.ts @@ -24,8 +24,7 @@ import { FtrProviderContext } from '../../../../../ftr_provider_context'; export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless read_lists', () => { describe('reading lists', () => { @@ -52,7 +51,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); @@ -71,7 +70,7 @@ export default ({ getService }: FtrProviderContext) => { const bodyToCompare = removeListServerGeneratedProperties(body); expect(bodyToCompare).to.eql( - getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME) + getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()) ); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/update_lists.ts b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/update_lists.ts index 28084f54d2abe..21d1db4ff3e94 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/update_lists.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/lists_and_exception_lists/lists_items/trial_license_complete_tier/lists/update_lists.ts @@ -25,8 +25,7 @@ export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); const log = getService('log'); const retry = getService('retry'); - const config = getService('config'); - const ELASTICSEARCH_USERNAME = config.get('servers.kibana.username'); + const utils = getService('securitySolutionUtils'); describe('@ess @serverless update_lists', () => { describe('update lists', () => { @@ -59,7 +58,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', version: 2, }; @@ -89,7 +88,7 @@ export default ({ getService }: FtrProviderContext) => { .expect(200); const outputList: Partial = { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', version: 2, }; @@ -188,7 +187,7 @@ export default ({ getService }: FtrProviderContext) => { const { body } = await supertest.put(LIST_URL).set('kbn-xsrf', 'true').send(updatedList); const outputList: Partial = { - ...getListResponseMockWithoutAutoGeneratedValues(ELASTICSEARCH_USERNAME), + ...getListResponseMockWithoutAutoGeneratedValues(await utils.getUsername()), name: 'some other name', description: 'some other description', version: 2, From f8589f890e4bc09328c562c7a701bf2a63f1e6cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yulia=20=C4=8Cech?= <6585477+yuliacech@users.noreply.github.com> Date: Tue, 25 Jun 2024 15:48:16 +0200 Subject: [PATCH 02/22] [Console Monaco migration] Fixes (#186479) ## Summary Fixes https://github.com/elastic/kibana/issues/184927 Fixes https://github.com/elastic/kibana/issues/184584 Fixes https://github.com/elastic/kibana/issues/184447 This PR fixes various issues in the migrated Console: - The url params with whitespaces are now parsed correctly and the whole values is sent in the request (https://github.com/elastic/kibana/issues/184927) - The autocomplete for fields only shows the fields of the current index (https://github.com/elastic/kibana/issues/184584) - The popup with autocomplete suggestion is not covered by the resizer bar (https://github.com/elastic/kibana/issues/184447) #### How to test 1. Send a request with a url param that contains a whitespace, for example `GET _search?q="test test"`. The request should be executed correctly. 2. Create an index with only 1 field ``` PUT field_test/_doc/1 { "test": 1 } ``` Try a search query with the fields autocomplete and check that only 1 field is suggested ``` GET field_test/_search { "query": { "match": { " ``` 3. Check that the popup with autocomplete suggestions is not covered by the resizer bar ### Checklist Delete any items that are not applicable to this PR. - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [ ] If a plugin configuration key changed, check if it needs to be allowlisted in the cloud and added to the [docker list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker) - [ ] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [ ] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) ### Risk Matrix Delete this section if it is not applicable to this PR. Before closing this PR, invite QA, stakeholders, and other developers to identify risks that should be tested prior to the change/feature release. When forming the risk matrix, consider some of the following examples and how they may potentially impact the change: | Risk | Probability | Severity | Mitigation/Notes | |---------------------------|-------------|----------|-------------------------| | Multiple Spaces—unexpected behavior in non-default Kibana Space. | Low | High | Integration tests will verify that all features are still supported in non-default Kibana Space and when user switches between spaces. | | Multiple nodes—Elasticsearch polling might have race conditions when multiple Kibana nodes are polling for the same tasks. | High | Low | Tasks are idempotent, so executing them multiple times will not result in logical error, but will degrade performance. To test for this case we add plenty of unit tests around this logic and document manual testing procedure. | | Code should gracefully handle cases when feature X or plugin Y are disabled. | Medium | High | Unit tests will verify that any feature flag or plugin combination still results in our service operational. | | [See more potential risk examples](https://github.com/elastic/kibana/blob/main/RISK_MATRIX.mdx) | ### For maintainers - [ ] This was checked for breaking API changes and was [labeled appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --- .../editor/monaco/utils/tokens_utils.test.ts | 5 ++++ .../editor/monaco/utils/tokens_utils.ts | 19 +++++++++++++- .../models/sense_editor/integration.test.js | 4 --- .../index_autocomplete_component.js | 8 ++++++ src/plugins/console/public/lib/kb/kb.test.js | 4 +-- src/plugins/console/public/styles/_app.scss | 8 ++++++ .../apps/console/monaco/_autocomplete.ts | 26 +++++++++++++++++++ .../apps/console/monaco/_console.ts | 3 +-- test/functional/page_objects/console_page.ts | 6 ++++- 9 files changed, 73 insertions(+), 10 deletions(-) diff --git a/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.test.ts b/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.test.ts index 600b5f4a98e4a..e31864e4c05c6 100644 --- a/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.test.ts +++ b/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.test.ts @@ -25,6 +25,11 @@ describe('tokens_utils', () => { const result = removeTrailingWhitespaces(url); expect(result).toBe('_search'); }); + it(`doesn't split a query parameter with whitespaces`, () => { + const url = '_search?q="with whitespace"'; + const result = removeTrailingWhitespaces(url); + expect(result).toBe(url); + }); }); describe('parseBody', () => { diff --git a/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.ts b/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.ts index decbe0d4fdd9a..2ff755b12af1d 100644 --- a/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.ts +++ b/src/plugins/console/public/application/containers/editor/monaco/utils/tokens_utils.ts @@ -405,7 +405,24 @@ export const parseBody = (value: string): string[] => { * Ideally the parser would do that, but currently they are included in url. */ export const removeTrailingWhitespaces = (url: string): string => { - return url.trim().split(whitespacesRegex)[0]; + let index = 0; + let whitespaceIndex = -1; + let isQueryParam = false; + let char = url[index]; + while (char) { + if (char === '"') { + isQueryParam = !isQueryParam; + } else if (char === ' ' && !isQueryParam) { + whitespaceIndex = index; + break; + } + index++; + char = url[index]; + } + if (whitespaceIndex > 0) { + return url.slice(0, whitespaceIndex); + } + return url; }; /* diff --git a/src/plugins/console/public/application/models/sense_editor/integration.test.js b/src/plugins/console/public/application/models/sense_editor/integration.test.js index 8327e4d15da78..f74a0a0c10341 100644 --- a/src/plugins/console/public/application/models/sense_editor/integration.test.js +++ b/src/plugins/console/public/application/models/sense_editor/integration.test.js @@ -948,8 +948,6 @@ describe('Integration', () => { autoCompleteSet: [ tt('field1.1.1', { f: 1 }, 'string'), tt('field1.1.2', { f: 1 }, 'string'), - tt('field2.1.1', { f: 1 }, 'string'), - tt('field2.1.2', { f: 1 }, 'string'), ], }, { @@ -958,8 +956,6 @@ describe('Integration', () => { autoCompleteSet: [ { name: 'field1.1.1', meta: 'string' }, { name: 'field1.1.2', meta: 'string' }, - { name: 'field2.1.1', meta: 'string' }, - { name: 'field2.1.2', meta: 'string' }, ], }, ] diff --git a/src/plugins/console/public/lib/autocomplete/components/index_autocomplete_component.js b/src/plugins/console/public/lib/autocomplete/components/index_autocomplete_component.js index 752e69c09614e..7615c511148b0 100644 --- a/src/plugins/console/public/lib/autocomplete/components/index_autocomplete_component.js +++ b/src/plugins/console/public/lib/autocomplete/components/index_autocomplete_component.js @@ -24,4 +24,12 @@ export class IndexAutocompleteComponent extends ListComponent { } return !_.find(tokens, nonValidIndexType); } + + getDefaultTermMeta() { + return 'index'; + } + + getContextKey() { + return 'indices'; + } } diff --git a/src/plugins/console/public/lib/kb/kb.test.js b/src/plugins/console/public/lib/kb/kb.test.js index e14ceb6445c8d..b23bdf8ea0846 100644 --- a/src/plugins/console/public/lib/kb/kb.test.js +++ b/src/plugins/console/public/lib/kb/kb.test.js @@ -133,12 +133,12 @@ describe('Knowledge base', () => { ); indexTest('Index integration 2', ['index1'], [], { - index: ['index1'], + indices: ['index1'], autoCompleteSet: ['_multi_indices', '_single_index'], }); indexTest('Index integration 2', [['index1', 'index2']], [], { - index: ['index1', 'index2'], + indices: ['index1', 'index2'], autoCompleteSet: ['_multi_indices', '_single_index'], }); }); diff --git a/src/plugins/console/public/styles/_app.scss b/src/plugins/console/public/styles/_app.scss index a4a7469a69bfe..f2353821ec93f 100644 --- a/src/plugins/console/public/styles/_app.scss +++ b/src/plugins/console/public/styles/_app.scss @@ -133,3 +133,11 @@ .console__monaco_editor__selectedRequests { background: transparentize($euiColorLightShade, .3); } +/* + * The z-index for the autocomplete suggestions popup + */ + +.kibanaCodeEditor .monaco-editor .suggest-widget { + // the value needs to be above the z-index of the resizer bar + z-index: $euiZLevel1 + 2; +} diff --git a/test/functional/apps/console/monaco/_autocomplete.ts b/test/functional/apps/console/monaco/_autocomplete.ts index 96b2461b62545..bb81216111ddd 100644 --- a/test/functional/apps/console/monaco/_autocomplete.ts +++ b/test/functional/apps/console/monaco/_autocomplete.ts @@ -371,5 +371,31 @@ GET _search }); }); }); + + describe('index fields autocomplete', () => { + const indexName = `index_field_test-${Date.now()}-${Math.random()}`; + + before(async () => { + await PageObjects.console.monaco.clearEditorText(); + // create an index with only 1 field + await PageObjects.console.monaco.enterText(`PUT ${indexName}/_doc/1\n{\n"test":1\n}`); + await PageObjects.console.clickPlay(); + }); + + after(async () => { + await PageObjects.console.monaco.clearEditorText(); + // delete the test index + await PageObjects.console.monaco.enterText(`DELETE ${indexName}`); + await PageObjects.console.clickPlay(); + }); + + it('fields autocomplete only shows fields of the index', async () => { + await PageObjects.console.monaco.clearEditorText(); + await PageObjects.console.monaco.enterText('GET _search\n{\n"fields": ["'); + + expect(await PageObjects.console.monaco.getAutocompleteSuggestion(0)).to.be.eql('test'); + expect(await PageObjects.console.monaco.getAutocompleteSuggestion(1)).to.be.eql(undefined); + }); + }); }); } diff --git a/test/functional/apps/console/monaco/_console.ts b/test/functional/apps/console/monaco/_console.ts index 36bb893d5b90f..b48ba75529579 100644 --- a/test/functional/apps/console/monaco/_console.ts +++ b/test/functional/apps/console/monaco/_console.ts @@ -36,8 +36,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) { }); }); - // issue with the url params with whitespaces https://github.com/elastic/kibana/issues/184927 - it.skip('default request response should include `"timed_out" : false`', async () => { + it('default request response should include `"timed_out" : false`', async () => { const expectedResponseContains = `"timed_out": false`; await PageObjects.console.monaco.selectAllRequests(); await PageObjects.console.clickPlay(); diff --git a/test/functional/page_objects/console_page.ts b/test/functional/page_objects/console_page.ts index 84267de85a595..aae93bacc965c 100644 --- a/test/functional/page_objects/console_page.ts +++ b/test/functional/page_objects/console_page.ts @@ -77,7 +77,11 @@ export class ConsolePageObject extends FtrService { getAutocompleteSuggestion: async (index: number) => { const suggestionsWidget = await this.find.byClassName('suggest-widget'); const suggestions = await suggestionsWidget.findAllByClassName('monaco-list-row'); - const label = await suggestions[index].findByClassName('label-name'); + const suggestion = suggestions[index]; + if (!suggestion) { + return undefined; + } + const label = await suggestion.findByClassName('label-name'); return label.getVisibleText(); }, pressUp: async (shift: boolean = false) => { From bd5e302fbf50f65436d63400d0ef1767b8f55b07 Mon Sep 17 00:00:00 2001 From: Konrad Szwarc Date: Tue, 25 Jun 2024 15:54:07 +0200 Subject: [PATCH 03/22] [EDR Workflows] Register as AV by default (#186514) Enable "Register as AV" by default in policies when protections are enabled. Set it to "Sync with Malware protection level". https://github.com/elastic/kibana/assets/29123534/e82e2228-dc23-48d4-8439-51cbc1ec6edc --- .../common/endpoint/models/policy_config.ts | 6 +-- .../endpoint/models/policy_config_helpers.ts | 5 +++ .../policy/store/policy_details/index.test.ts | 4 +- .../antivirus_registration_card.test.tsx | 10 +++-- .../cards/malware_protections_card.test.tsx | 6 +-- .../protection_setting_card_switch.test.tsx | 44 ++++++++++++++++--- .../policy/view/policy_settings_form/mocks.ts | 24 +++++++--- .../policy_settings_form.test.tsx | 18 ++++---- .../policy_settings_layout.test.tsx | 6 ++- 9 files changed, 89 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts b/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts index 4ca15c05ee1c1..9ed0d20aee883 100644 --- a/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts +++ b/x-pack/plugins/security_solution/common/endpoint/models/policy_config.ts @@ -6,7 +6,7 @@ */ import type { PolicyConfig } from '../types'; -import { ProtectionModes, AntivirusRegistrationModes } from '../types'; +import { AntivirusRegistrationModes, ProtectionModes } from '../types'; import { isBillablePolicy } from './policy_config_helpers'; @@ -82,8 +82,8 @@ export const policyFactory = ( file: 'info', }, antivirus_registration: { - mode: AntivirusRegistrationModes.disabled, - enabled: false, + mode: AntivirusRegistrationModes.sync, + enabled: true, // Defaults to true since Malware protection is set to prevent and mode is set to sync }, attack_surface_reduction: { credential_hardening: { diff --git a/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.ts b/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.ts index 23ad015fc3b07..3f046e6ec15de 100644 --- a/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.ts +++ b/x-pack/plugins/security_solution/common/endpoint/models/policy_config_helpers.ts @@ -143,6 +143,11 @@ const getDisabledWindowsSpecificProtections = (policy: PolicyConfig) => ({ ...policy.windows.ransomware, mode: ProtectionModes.off, }, + antivirus_registration: { + ...policy.windows.antivirus_registration, + mode: AntivirusRegistrationModes.disabled, + enabled: false, + }, attack_surface_reduction: { ...policy.windows.attack_surface_reduction, credential_hardening: { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts index 87f547ced403a..57154ea39a3d5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/store/policy_details/index.test.ts @@ -325,8 +325,8 @@ describe('policy details: ', () => { }, logging: { file: 'info' }, antivirus_registration: { - enabled: false, - mode: 'disabled', + enabled: true, + mode: 'sync_with_malware_prevent', }, }, mac: { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/antivirus_registration_card.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/antivirus_registration_card.test.tsx index 7d29148aeccb6..b9e563ec7e6e1 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/antivirus_registration_card.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/antivirus_registration_card.test.tsx @@ -41,7 +41,7 @@ describe('Policy Form Antivirus Registration Card', () => { getRadioButton = (testSubject) => renderResult.getByTestId(testSubject).querySelector('input')!; }); - it('should render in edit mode', () => { + it('should render in edit mode with default value selected', () => { render(); expect(renderResult.getByTestId(antivirusTestSubj.radioButtons)).toBeTruthy(); @@ -49,6 +49,10 @@ describe('Policy Form Antivirus Registration Card', () => { expect(getRadioButton(antivirusTestSubj.disabledRadioButton)).not.toHaveAttribute('disabled'); expect(getRadioButton(antivirusTestSubj.enabledRadioButton)).not.toHaveAttribute('disabled'); expect(getRadioButton(antivirusTestSubj.syncRadioButton)).not.toHaveAttribute('disabled'); + + expect(getRadioButton(antivirusTestSubj.disabledRadioButton).checked).toBe(false); + expect(getRadioButton(antivirusTestSubj.enabledRadioButton).checked).toBe(false); + expect(getRadioButton(antivirusTestSubj.syncRadioButton).checked).toBe(true); }); it('should check `disabled` radio button if `antivirus_registration.mode` is disabled', () => { @@ -144,9 +148,9 @@ describe('Policy Form Antivirus Registration Card', () => { render(); expectIsViewOnly(renderResult.getByTestId(antivirusTestSubj.card)); - expect(getRadioButton(antivirusTestSubj.disabledRadioButton).checked).toBe(true); + expect(getRadioButton(antivirusTestSubj.disabledRadioButton).checked).toBe(false); expect(getRadioButton(antivirusTestSubj.enabledRadioButton).checked).toBe(false); - expect(getRadioButton(antivirusTestSubj.syncRadioButton).checked).toBe(false); + expect(getRadioButton(antivirusTestSubj.syncRadioButton).checked).toBe(true); }); it('should render in view mode (option enabled)', () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.test.tsx index db1074f031953..bdaeb561e6c5f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/cards/malware_protections_card.test.tsx @@ -74,7 +74,7 @@ describe('Policy Malware Protections Card', () => { (feature: { name: 'blocklist' | 'onWriteScan'; config: string; deafult: boolean }) => { it(`should set ${feature.name} to disabled if malware is turned off`, () => { const expectedUpdatedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedUpdatedPolicy, true); + setMalwareMode({ policy: expectedUpdatedPolicy, turnOff: true }); render(); userEvent.click(renderResult.getByTestId(testSubj.enableDisableSwitch)); @@ -86,9 +86,9 @@ describe('Policy Malware Protections Card', () => { it(`should set ${feature.name} to enabled if malware is turned on`, () => { const expectedUpdatedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedUpdatedPolicy); + setMalwareMode({ policy: expectedUpdatedPolicy }); const initialPolicy = cloneDeep(formProps.policy); - setMalwareMode(initialPolicy, true); + setMalwareMode({ policy: initialPolicy, turnOff: true }); render(initialPolicy); userEvent.click(renderResult.getByTestId(testSubj.enableDisableSwitch)); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.test.tsx index 1c57d6d20163b..ab1b88a64d105 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/components/protection_setting_card_switch.test.tsx @@ -69,7 +69,11 @@ describe('Policy form ProtectionSettingCardSwitch component', () => { it('should be able to disable it', () => { const expectedUpdatedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedUpdatedPolicy, true, true, false); + setMalwareMode({ + policy: expectedUpdatedPolicy, + turnOff: true, + includeSubfeatures: false, + }); render(); userEvent.click(renderResult.getByTestId('test')); @@ -80,9 +84,17 @@ describe('Policy form ProtectionSettingCardSwitch component', () => { }); it('should be able to enable it', () => { - setMalwareMode(formProps.policy, true, true, false); + setMalwareMode({ + policy: formProps.policy, + turnOff: true, + includeSubfeatures: false, + }); const expectedUpdatedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedUpdatedPolicy, false, true, false); + setMalwareMode({ + policy: expectedUpdatedPolicy, + turnOff: false, + includeSubfeatures: false, + }); render(); userEvent.click(renderResult.getByTestId('test')); @@ -100,7 +112,11 @@ describe('Policy form ProtectionSettingCardSwitch component', () => { }); const expectedPolicyDataBeforeAdditionalCallback = cloneDeep(formProps.policy); - setMalwareMode(expectedPolicyDataBeforeAdditionalCallback, true, true, false); + setMalwareMode({ + policy: expectedPolicyDataBeforeAdditionalCallback, + turnOff: true, + includeSubfeatures: false, + }); const expectedUpdatedPolicy = cloneDeep(expectedPolicyDataBeforeAdditionalCallback); expectedUpdatedPolicy.windows.popup.malware.message = 'foo'; @@ -134,7 +150,12 @@ describe('Policy form ProtectionSettingCardSwitch component', () => { it('should NOT update notification settings when disabling', () => { const expectedUpdatedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedUpdatedPolicy, true, false, false); + setMalwareMode({ + policy: expectedUpdatedPolicy, + turnOff: true, + includePopup: false, + includeSubfeatures: false, + }); render(); userEvent.click(renderResult.getByTestId('test')); @@ -146,7 +167,12 @@ describe('Policy form ProtectionSettingCardSwitch component', () => { it('should NOT update notification settings when enabling', () => { const expectedUpdatedPolicy = cloneDeep(formProps.policy); - setMalwareMode(formProps.policy, true, false, false); + setMalwareMode({ + policy: formProps.policy, + turnOff: true, + includePopup: false, + includeSubfeatures: false, + }); render(); userEvent.click(renderResult.getByTestId('test')); @@ -176,7 +202,11 @@ describe('Policy form ProtectionSettingCardSwitch component', () => { }); it('should show option when unchecked', () => { - setMalwareMode(formProps.policy, true, true, false); + setMalwareMode({ + policy: formProps.policy, + turnOff: true, + includeSubfeatures: false, + }); render(); expect(renderResult.getByTestId('test-label')).toHaveTextContent(exactMatchText('Malware')); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/mocks.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/mocks.ts index c2af340726de8..b2ef180dd4bfd 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/mocks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/mocks.ts @@ -201,13 +201,21 @@ export const exactMatchText = (text: string): RegExp => { * @param turnOff * @param includePopup * @param includeSubfeatures + * @param includeAntivirus */ -export const setMalwareMode = ( - policy: PolicyConfig, - turnOff: boolean = false, - includePopup: boolean = true, - includeSubfeatures: boolean = true -) => { +export const setMalwareMode = ({ + policy, + turnOff = false, + includePopup = true, + includeSubfeatures = true, + includeAntivirus = false, +}: { + policy: PolicyConfig; + turnOff?: boolean; + includePopup?: boolean; + includeSubfeatures?: boolean; + includeAntivirus?: boolean; +}) => { const mode = turnOff ? ProtectionModes.off : ProtectionModes.prevent; const enableValue = mode !== ProtectionModes.off; @@ -215,6 +223,10 @@ export const setMalwareMode = ( set(policy, 'mac.malware.mode', mode); set(policy, 'linux.malware.mode', mode); + if (includeAntivirus) { + set(policy, 'windows.antivirus_registration.enabled', !turnOff); + } + if (includePopup) { set(policy, 'windows.popup.malware.enabled', enableValue); set(policy, 'mac.popup.malware.enabled', enableValue); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.test.tsx index 76928a8de4179..9607e5949d9a0 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_form/policy_settings_form.test.tsx @@ -119,13 +119,13 @@ describe('Endpoint Policy Settings Form', () => { describe('changing malware when antivirus registration is synced with malware', () => { it('should enable antivirus registration when malware is enabled', () => { setAntivirusRegistration(formProps.policy, AntivirusRegistrationModes.sync, false); - setMalwareMode(formProps.policy, true); + setMalwareMode({ policy: formProps.policy, turnOff: true }); render(); userEvent.click(renderResult.getByTestId(testSubj.malware.enableDisableSwitch)); const expectedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedPolicy); + setMalwareMode({ policy: expectedPolicy }); setAntivirusRegistration(expectedPolicy, AntivirusRegistrationModes.sync, true); expectOnChangeToBeCalledWith(expectedPolicy); }); @@ -137,14 +137,14 @@ describe('Endpoint Policy Settings Form', () => { userEvent.click(renderResult.getByTestId(testSubj.malware.enableDisableSwitch)); const expectedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedPolicy, true); + setMalwareMode({ policy: expectedPolicy, turnOff: true }); setAntivirusRegistration(expectedPolicy, AntivirusRegistrationModes.sync, false); expectOnChangeToBeCalledWith(expectedPolicy); }); it('should disable antivirus registration when malware is set to detect only', () => { setAntivirusRegistration(formProps.policy, AntivirusRegistrationModes.sync, true); - setMalwareMode(formProps.policy); + setMalwareMode({ policy: formProps.policy }); render(); clickOnRadio(testSubj.malware.protectionDetectRadio); @@ -159,13 +159,13 @@ describe('Endpoint Policy Settings Form', () => { describe('changing malware when antivirus registration is NOT synced with malware', () => { it('should not change antivirus registration when malware is enabled', () => { setAntivirusRegistration(formProps.policy, AntivirusRegistrationModes.disabled, false); - setMalwareMode(formProps.policy, true); + setMalwareMode({ policy: formProps.policy, turnOff: true }); render(); userEvent.click(renderResult.getByTestId(testSubj.malware.enableDisableSwitch)); const expectedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedPolicy); + setMalwareMode({ policy: expectedPolicy }); expectOnChangeToBeCalledWith(expectedPolicy); }); @@ -176,13 +176,13 @@ describe('Endpoint Policy Settings Form', () => { userEvent.click(renderResult.getByTestId(testSubj.malware.enableDisableSwitch)); const expectedPolicy = cloneDeep(formProps.policy); - setMalwareMode(expectedPolicy, true); + setMalwareMode({ policy: expectedPolicy, turnOff: true }); expectOnChangeToBeCalledWith(expectedPolicy); }); it('should not change antivirus registration when malware is set to detect only', () => { setAntivirusRegistration(formProps.policy, AntivirusRegistrationModes.enabled, true); - setMalwareMode(formProps.policy); + setMalwareMode({ policy: formProps.policy }); render(); clickOnRadio(testSubj.malware.protectionDetectRadio); @@ -219,7 +219,7 @@ describe('Endpoint Policy Settings Form', () => { describe('changing antivirus registration mode when malware is disabled', () => { beforeEach(() => { - setMalwareMode(formProps.policy, true); + setMalwareMode({ policy: formProps.policy, turnOff: true }); }); it('should disable antivirus registration when set to sync', () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_layout/policy_settings_layout.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_layout/policy_settings_layout.test.tsx index bfc0ec3691363..4a685bb475810 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_layout/policy_settings_layout.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_settings_layout/policy_settings_layout.test.tsx @@ -93,7 +93,11 @@ describe('When rendering PolicySettingsLayout', () => { // Turn off malware userEvent.click(getByTestId(testSubj.malware.enableDisableSwitch)); - setMalwareMode(policySettings, true); + setMalwareMode({ + policy: policySettings, + turnOff: true, + includeAntivirus: true, + }); // Turn off Behaviour Protection userEvent.click(getByTestId(testSubj.behaviour.enableDisableSwitch)); From 3d968fc421410a8851f6faa41f0b7b8da087c1e1 Mon Sep 17 00:00:00 2001 From: Philippe Oberti Date: Tue, 25 Jun 2024 08:59:19 -0500 Subject: [PATCH 04/22] [Security Solution][Notes] - add create note to flyout notes tab (#186807) --- .../public/common/mock/global_state.ts | 2 + .../left/components/add_note.test.tsx | 84 ++++++++ .../left/components/add_note.tsx | 114 +++++++++++ .../left/components/notes_details.tsx | 10 +- .../left/components/notes_list.test.tsx | 16 +- .../left/components/notes_list.tsx | 19 +- .../left/components/test_ids.ts | 3 + .../security_solution/public/notes/api/api.ts | 23 +++ .../public/notes/store/notes.slice.test.ts | 185 +++++++++++++----- .../public/notes/store/notes.slice.ts | 39 +++- 10 files changed, 430 insertions(+), 65 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.test.tsx create mode 100644 x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.tsx diff --git a/x-pack/plugins/security_solution/public/common/mock/global_state.ts b/x-pack/plugins/security_solution/public/common/mock/global_state.ts index 2a61b964774ee..7a865a4be9f04 100644 --- a/x-pack/plugins/security_solution/public/common/mock/global_state.ts +++ b/x-pack/plugins/security_solution/public/common/mock/global_state.ts @@ -520,9 +520,11 @@ export const mockGlobalState: State = { }, status: { fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Idle, }, error: { fetchNotesByDocumentId: null, + createNote: null, }, }, }; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.test.tsx new file mode 100644 index 0000000000000..95e6591dec9cb --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.test.tsx @@ -0,0 +1,84 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; +import { createMockStore, mockGlobalState, TestProviders } from '../../../../common/mock'; +import { AddNote, CREATE_NOTE_ERROR } from './add_note'; +import { ADD_NOTE_BUTTON_TEST_ID, ADD_NOTE_MARKDOWN_TEST_ID } from './test_ids'; +import { ReqStatus } from '../../../../notes/store/notes.slice'; + +const mockAddError = jest.fn(); +jest.mock('../../../../common/hooks/use_app_toasts', () => ({ + useAppToasts: () => ({ + addError: mockAddError, + }), +})); + +const mockDispatch = jest.fn(); +jest.mock('react-redux', () => { + const original = jest.requireActual('react-redux'); + return { + ...original, + useDispatch: () => mockDispatch, + }; +}); + +const renderAddNote = () => + render( + + + + ); + +describe('AddNote', () => { + it('should render the markdown and add button components', () => { + const { getByTestId } = renderAddNote(); + + expect(getByTestId(ADD_NOTE_MARKDOWN_TEST_ID)).toBeInTheDocument(); + expect(getByTestId(ADD_NOTE_BUTTON_TEST_ID)).toBeInTheDocument(); + }); + + it('should create note', () => { + const { getByTestId } = renderAddNote(); + + getByTestId(ADD_NOTE_BUTTON_TEST_ID).click(); + + expect(mockDispatch).toHaveBeenCalled(); + }); + + it('should render the add note button in loading state while creating a new note', () => { + const state = { ...mockGlobalState }; + state.notes.status.createNote = ReqStatus.Loading; + const store = createMockStore(state); + + const { container } = render( + + + + ); + + expect(container.querySelector('.euiLoadingSpinner')).toBeInTheDocument(); + }); + + it('should render error toast if create a note fails', () => { + const state = { ...mockGlobalState }; + state.notes.status.createNote = ReqStatus.Failed; + state.notes.error.createNote = { type: 'http', status: 500 }; + const store = createMockStore(state); + + render( + + + + ); + + expect(mockAddError).toHaveBeenCalledWith(null, { + title: CREATE_NOTE_ERROR, + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.tsx new file mode 100644 index 0000000000000..2b455e35eddb1 --- /dev/null +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.tsx @@ -0,0 +1,114 @@ +/* + * 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, { memo, useCallback, useEffect, useState } from 'react'; +import { + EuiButton, + EuiComment, + EuiCommentList, + EuiFlexGroup, + EuiFlexItem, + EuiSpacer, +} from '@elastic/eui'; +import { useDispatch, useSelector } from 'react-redux'; +import { i18n } from '@kbn/i18n'; +import { ADD_NOTE_BUTTON_TEST_ID, ADD_NOTE_MARKDOWN_TEST_ID } from './test_ids'; +import { useAppToasts } from '../../../../common/hooks/use_app_toasts'; +import type { State } from '../../../../common/store'; +import { + createNote, + ReqStatus, + selectCreateNoteError, + selectCreateNoteStatus, +} from '../../../../notes/store/notes.slice'; +import { MarkdownEditor } from '../../../../common/components/markdown_editor'; + +export const MARKDOWN_ARIA_LABEL = i18n.translate( + 'xpack.securitySolution.notes.markdownAriaLabel', + { + defaultMessage: 'Note', + } +); +export const ADD_NOTE_BUTTON = i18n.translate('xpack.securitySolution.notes.addNoteBtnLabel', { + defaultMessage: 'Add note', +}); +export const CREATE_NOTE_ERROR = i18n.translate( + 'xpack.securitySolution.notes.createNoteErrorLabel', + { + defaultMessage: 'Error create note', + } +); + +export interface AddNewNoteProps { + /** + * Id of the document + */ + eventId: string; +} + +/** + * Renders a markdown editor and a add button to create new notes + */ +export const AddNote = memo(({ eventId }: AddNewNoteProps) => { + const dispatch = useDispatch(); + const { addError: addErrorToast } = useAppToasts(); + const [editorValue, setEditorValue] = useState(''); + + const createStatus = useSelector((state: State) => selectCreateNoteStatus(state)); + const createError = useSelector((state: State) => selectCreateNoteError(state)); + + const addNote = useCallback(() => { + dispatch( + createNote({ + note: { + timelineId: '', + eventId, + note: editorValue, + }, + }) + ); + setEditorValue(''); + }, [dispatch, editorValue, eventId]); + + useEffect(() => { + if (createStatus === ReqStatus.Failed && createError) { + addErrorToast(null, { + title: CREATE_NOTE_ERROR, + }); + } + }, [addErrorToast, createError, createStatus]); + + return ( + <> + + + {}} + /> + + + + + + + {ADD_NOTE_BUTTON} + + + + + ); +}); + +AddNote.displayName = 'AddNote'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx index b378fc2e9f270..94e5233ff8d70 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_details.tsx @@ -7,6 +7,8 @@ import React, { memo, useEffect } from 'react'; import { useDispatch } from 'react-redux'; +import { EuiSpacer } from '@elastic/eui'; +import { AddNote } from './add_note'; import { NotesList } from './notes_list'; import { fetchNotesByDocumentId } from '../../../../notes/store/notes.slice'; import { useDocumentDetailsContext } from '../../shared/context'; @@ -23,7 +25,13 @@ export const NotesDetails = memo(() => { dispatch(fetchNotesByDocumentId({ documentId: eventId })); }, [dispatch, eventId]); - return ; + return ( + <> + + + + + ); }); NotesDetails.displayName = 'NotesDetails'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.test.tsx index f13c0fb5df9df..82dfeac7e60ad 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.test.tsx @@ -7,7 +7,7 @@ import { render } from '@testing-library/react'; import React from 'react'; -import { NOTES_COMMENT_TEST_ID, NOTES_LOADING_TEST_ID } from './test_ids'; +import { ADD_NOTE_LOADING_TEST_ID, NOTES_COMMENT_TEST_ID, NOTES_LOADING_TEST_ID } from './test_ids'; import { createMockStore, mockGlobalState, TestProviders } from '../../../../common/mock'; import { FETCH_NOTES_ERROR, NO_NOTES, NotesList } from './notes_list'; import { ReqStatus } from '../../../../notes/store/notes.slice'; @@ -77,4 +77,18 @@ describe('NotesList', () => { title: FETCH_NOTES_ERROR, }); }); + + it('should render create loading when user create a new note', () => { + const state = { ...mockGlobalState }; + state.notes.status.createNote = ReqStatus.Loading; + const store = createMockStore(state); + + const { getByTestId } = render( + + + + ); + + expect(getByTestId(ADD_NOTE_LOADING_TEST_ID)).toBeInTheDocument(); + }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.tsx index af0535803adf0..a34afe6ad0e50 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.tsx @@ -5,16 +5,17 @@ * 2.0. */ -import React, { useEffect } from 'react'; +import React, { memo, useEffect } from 'react'; import { EuiComment, EuiCommentList, EuiLoadingElastic, EuiMarkdownFormat } from '@elastic/eui'; import { useSelector } from 'react-redux'; import { FormattedRelative } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { NOTES_COMMENT_TEST_ID, NOTES_LOADING_TEST_ID } from './test_ids'; +import { ADD_NOTE_LOADING_TEST_ID, NOTES_COMMENT_TEST_ID, NOTES_LOADING_TEST_ID } from './test_ids'; import type { State } from '../../../../common/store'; import type { Note } from '../../../../../common/api/timeline'; import { ReqStatus, + selectCreateNoteStatus, selectFetchNotesByDocumentIdError, selectFetchNotesByDocumentIdStatus, selectNotesByDocumentId, @@ -25,7 +26,7 @@ export const ADDED_A_NOTE = i18n.translate('xpack.securitySolution.notes.addedAN defaultMessage: 'added a note', }); export const FETCH_NOTES_ERROR = i18n.translate( - 'xpack.securitySolution.notes.fetchNoteErrorLabel', + 'xpack.securitySolution.notes.fetchNotesErrorLabel', { defaultMessage: 'Error fetching notes', } @@ -44,14 +45,17 @@ export interface NotesListProps { /** * Renders a list of notes for the document. * If a note belongs to a timeline, a timeline icon will be shown the top right corner. + * When a note is being created, the component renders a loading spinner when the new note is about to be added. */ -export const NotesList = ({ eventId }: NotesListProps) => { +export const NotesList = memo(({ eventId }: NotesListProps) => { const { addError: addErrorToast } = useAppToasts(); const fetchStatus = useSelector((state: State) => selectFetchNotesByDocumentIdStatus(state)); const fetchError = useSelector((state: State) => selectFetchNotesByDocumentIdError(state)); const notes: Note[] = useSelector((state: State) => selectNotesByDocumentId(state, eventId)); + const createStatus = useSelector((state: State) => selectCreateNoteStatus(state)); + useEffect(() => { if (fetchStatus === ReqStatus.Failed && fetchError) { addErrorToast(null, { @@ -73,7 +77,7 @@ export const NotesList = ({ eventId }: NotesListProps) => { {notes.map((note, index) => ( {note.created && }} event={ADDED_A_NOTE} @@ -81,8 +85,11 @@ export const NotesList = ({ eventId }: NotesListProps) => { {note.note || ''} ))} + {createStatus === ReqStatus.Loading && ( + + )} ); -}; +}); NotesList.displayName = 'NotesList'; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts index 2fb6c560d5990..cd49334abea7e 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts @@ -94,3 +94,6 @@ export const INVESTIGATION_GUIDE_LOADING_TEST_ID = `${INVESTIGATION_GUIDE_TEST_I export const NOTES_LOADING_TEST_ID = `${PREFIX}NotesLoading` as const; export const NOTES_COMMENT_TEST_ID = `${PREFIX}NotesComment` as const; +export const ADD_NOTE_LOADING_TEST_ID = `${PREFIX}AddNotesLoading` as const; +export const ADD_NOTE_MARKDOWN_TEST_ID = `${PREFIX}AddNotesMarkdown` as const; +export const ADD_NOTE_BUTTON_TEST_ID = `${PREFIX}AddNotesButton` as const; diff --git a/x-pack/plugins/security_solution/public/notes/api/api.ts b/x-pack/plugins/security_solution/public/notes/api/api.ts index bac685e75e009..c1090de4fe631 100644 --- a/x-pack/plugins/security_solution/public/notes/api/api.ts +++ b/x-pack/plugins/security_solution/public/notes/api/api.ts @@ -6,6 +6,29 @@ */ import * as uuid from 'uuid'; +import type { BareNote, Note } from '../../../common/api/timeline'; +import { KibanaServices } from '../../common/lib/kibana'; +import { NOTE_URL } from '../../../common/constants'; + +/** + * Adds a new note. + * This code is very close to the persistNote found in x-pack/plugins/security_solution/public/timelines/containers/notes/api.ts. + * // TODO remove the old method when the transition to the new notes system is complete + */ +export const createNote = async ({ note }: { note: BareNote }) => { + try { + const response = await KibanaServices.get().http.patch<{ + data: { persistNote: { code: number; message: string; note: Note } }; + }>(NOTE_URL, { + method: 'PATCH', + body: JSON.stringify({ note }), + version: '2023-10-31', + }); + return response.data.persistNote.note; + } catch (err) { + throw new Error(`Failed to stringify query: ${JSON.stringify(err)}`); + } +}; // TODO point to the correct API when it is available /** diff --git a/x-pack/plugins/security_solution/public/notes/store/notes.slice.test.ts b/x-pack/plugins/security_solution/public/notes/store/notes.slice.test.ts index 86ea158d80a44..6fd6437f00c27 100644 --- a/x-pack/plugins/security_solution/public/notes/store/notes.slice.test.ts +++ b/x-pack/plugins/security_solution/public/notes/store/notes.slice.test.ts @@ -6,11 +6,14 @@ */ import { + createNote, fetchNotesByDocumentId, initialNotesState, notesReducer, ReqStatus, selectAllNotes, + selectCreateNoteError, + selectCreateNoteStatus, selectFetchNotesByDocumentIdError, selectFetchNotesByDocumentIdStatus, selectNoteById, @@ -28,8 +31,8 @@ const initialNonEmptyState = { [mockNote.noteId]: mockNote, }, ids: [mockNote.noteId], - status: { fetchNotesByDocumentId: ReqStatus.Idle }, - error: { fetchNotesByDocumentId: null }, + status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Idle }, + error: { fetchNotesByDocumentId: null, createNote: null }, }; describe('notesSlice', () => { @@ -38,73 +41,141 @@ describe('notesSlice', () => { expect(notesReducer(initalEmptyState, { type: 'unknown' })).toEqual({ entities: {}, ids: [], - status: { fetchNotesByDocumentId: ReqStatus.Idle }, - error: { fetchNotesByDocumentId: null }, + status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Idle }, + error: { fetchNotesByDocumentId: null, createNote: null }, }); }); - it('should set correct state when fetching notes by document id', () => { - const action = { type: fetchNotesByDocumentId.pending.type }; + describe('fetchNotesByDocumentId', () => { + it('should set correct state when fetching notes by document id', () => { + const action = { type: fetchNotesByDocumentId.pending.type }; - expect(notesReducer(initalEmptyState, action)).toEqual({ - entities: {}, - ids: [], - status: { fetchNotesByDocumentId: ReqStatus.Loading }, - error: { fetchNotesByDocumentId: null }, + expect(notesReducer(initalEmptyState, action)).toEqual({ + entities: {}, + ids: [], + status: { + fetchNotesByDocumentId: ReqStatus.Loading, + createNote: ReqStatus.Idle, + }, + error: { fetchNotesByDocumentId: null, createNote: null }, + }); }); - }); - it('should set correct state when success on fetch notes by document id on an empty state', () => { - const action = { - type: fetchNotesByDocumentId.fulfilled.type, - payload: { - entities: { - notes: { - [mockNote.noteId]: mockNote, + it('should set correct state when success on fetch notes by document id on an empty state', () => { + const action = { + type: fetchNotesByDocumentId.fulfilled.type, + payload: { + entities: { + notes: { + [mockNote.noteId]: mockNote, + }, }, + result: [mockNote.noteId], }, - result: [mockNote.noteId], - }, - }; - - expect(notesReducer(initalEmptyState, action)).toEqual({ - entities: action.payload.entities.notes, - ids: action.payload.result, - status: { fetchNotesByDocumentId: ReqStatus.Succeeded }, - error: { fetchNotesByDocumentId: null }, + }; + + expect(notesReducer(initalEmptyState, action)).toEqual({ + entities: action.payload.entities.notes, + ids: action.payload.result, + status: { + fetchNotesByDocumentId: ReqStatus.Succeeded, + createNote: ReqStatus.Idle, + }, + error: { fetchNotesByDocumentId: null, createNote: null }, + }); }); - }); - it('should replace notes when success on fetch notes by document id on a non-empty state', () => { - const newMockNote = { ...mockNote, timelineId: 'timelineId' }; - const action = { - type: fetchNotesByDocumentId.fulfilled.type, - payload: { - entities: { - notes: { - [newMockNote.noteId]: newMockNote, + it('should replace notes when success on fetch notes by document id on a non-empty state', () => { + const newMockNote = { ...mockNote, timelineId: 'timelineId' }; + const action = { + type: fetchNotesByDocumentId.fulfilled.type, + payload: { + entities: { + notes: { + [newMockNote.noteId]: newMockNote, + }, }, + result: [newMockNote.noteId], + }, + }; + + expect(notesReducer(initialNonEmptyState, action)).toEqual({ + entities: action.payload.entities.notes, + ids: action.payload.result, + status: { + fetchNotesByDocumentId: ReqStatus.Succeeded, + createNote: ReqStatus.Idle, }, - result: [newMockNote.noteId], - }, - }; - - expect(notesReducer(initialNonEmptyState, action)).toEqual({ - entities: action.payload.entities.notes, - ids: action.payload.result, - status: { fetchNotesByDocumentId: ReqStatus.Succeeded }, - error: { fetchNotesByDocumentId: null }, + error: { fetchNotesByDocumentId: null, createNote: null }, + }); + }); + + it('should set correct state when error on fetch notes by document id', () => { + const action = { type: fetchNotesByDocumentId.rejected.type, error: 'error' }; + + expect(notesReducer(initalEmptyState, action)).toEqual({ + entities: {}, + ids: [], + status: { + fetchNotesByDocumentId: ReqStatus.Failed, + createNote: ReqStatus.Idle, + }, + error: { fetchNotesByDocumentId: 'error', createNote: null }, + }); }); }); - it('should set correct state when error on fetch notes by document id', () => { - const action = { type: fetchNotesByDocumentId.rejected.type, error: 'error' }; + describe('createNote', () => { + it('should set correct state when creating a note by document id', () => { + const action = { type: createNote.pending.type }; - expect(notesReducer(initalEmptyState, action)).toEqual({ - entities: {}, - ids: [], - status: { fetchNotesByDocumentId: ReqStatus.Failed }, - error: { fetchNotesByDocumentId: 'error' }, + expect(notesReducer(initalEmptyState, action)).toEqual({ + entities: {}, + ids: [], + status: { + fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Loading, + }, + error: { fetchNotesByDocumentId: null, createNote: null }, + }); + }); + + it('should set correct state when success on create a note by document id on an empty state', () => { + const action = { + type: createNote.fulfilled.type, + payload: { + entities: { + notes: { + [mockNote.noteId]: mockNote, + }, + }, + result: mockNote.noteId, + }, + }; + + expect(notesReducer(initalEmptyState, action)).toEqual({ + entities: action.payload.entities.notes, + ids: [action.payload.result], + status: { + fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Succeeded, + }, + error: { fetchNotesByDocumentId: null, createNote: null }, + }); + }); + + it('should set correct state when error on create a note by document id', () => { + const action = { type: createNote.rejected.type, error: 'error' }; + + expect(notesReducer(initalEmptyState, action)).toEqual({ + entities: {}, + ids: [], + status: { + fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Failed, + }, + error: { fetchNotesByDocumentId: null, createNote: 'error' }, + }); }); }); }); @@ -139,6 +210,14 @@ describe('notesSlice', () => { expect(selectFetchNotesByDocumentIdError(mockGlobalState)).toEqual(null); }); + it('should return create note by document id status', () => { + expect(selectCreateNoteStatus(mockGlobalState)).toEqual(ReqStatus.Idle); + }); + + it('should return create note by document id error', () => { + expect(selectCreateNoteError(mockGlobalState)).toEqual(null); + }); + it('should return all notes for an existing document id', () => { expect(selectNotesByDocumentId(mockGlobalState, '1')).toEqual([mockNote]); }); diff --git a/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts b/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts index da8745e15c448..d644539844dd5 100644 --- a/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts +++ b/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts @@ -9,10 +9,13 @@ import type { EntityState, SerializedError } from '@reduxjs/toolkit'; import { createAsyncThunk, createEntityAdapter, createSlice } from '@reduxjs/toolkit'; import { createSelector } from 'reselect'; import type { State } from '../../common/store'; -import { fetchNotesByDocumentId as fetchNotesByDocumentIdApi } from '../api/api'; -import type { NormalizedEntities } from './normalize'; -import { normalizeEntities } from './normalize'; -import type { Note } from '../../../common/api/timeline'; +import { + createNote as createNoteApi, + fetchNotesByDocumentId as fetchNotesByDocumentIdApi, +} from '../api/api'; +import type { NormalizedEntities, NormalizedEntity } from './normalize'; +import { normalizeEntities, normalizeEntity } from './normalize'; +import type { BareNote, Note } from '../../../common/api/timeline'; export enum ReqStatus { Idle = 'idle', @@ -29,9 +32,11 @@ interface HttpError { export interface NotesState extends EntityState { status: { fetchNotesByDocumentId: ReqStatus; + createNote: ReqStatus; }; error: { fetchNotesByDocumentId: SerializedError | HttpError | null; + createNote: SerializedError | HttpError | null; }; } @@ -42,9 +47,11 @@ const notesAdapter = createEntityAdapter({ export const initialNotesState: NotesState = notesAdapter.getInitialState({ status: { fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Idle, }, error: { fetchNotesByDocumentId: null, + createNote: null, }, }); @@ -58,6 +65,15 @@ export const fetchNotesByDocumentId = createAsyncThunk< return normalizeEntities(res); }); +export const createNote = createAsyncThunk, { note: BareNote }, {}>( + 'notes/createNote', + async (args) => { + const { note } = args; + const res = await createNoteApi({ note }); + return normalizeEntity(res); + } +); + const notesSlice = createSlice({ name: 'notes', initialState: initialNotesState, @@ -74,6 +90,17 @@ const notesSlice = createSlice({ .addCase(fetchNotesByDocumentId.rejected, (state, action) => { state.status.fetchNotesByDocumentId = ReqStatus.Failed; state.error.fetchNotesByDocumentId = action.payload ?? action.error; + }) + .addCase(createNote.pending, (state) => { + state.status.createNote = ReqStatus.Loading; + }) + .addCase(createNote.fulfilled, (state, action) => { + notesAdapter.addMany(state, action.payload.entities.notes); + state.status.createNote = ReqStatus.Succeeded; + }) + .addCase(createNote.rejected, (state, action) => { + state.status.createNote = ReqStatus.Failed; + state.error.createNote = action.payload ?? action.error; }); }, }); @@ -92,6 +119,10 @@ export const selectFetchNotesByDocumentIdStatus = (state: State) => export const selectFetchNotesByDocumentIdError = (state: State) => state.notes.error.fetchNotesByDocumentId; +export const selectCreateNoteStatus = (state: State) => state.notes.status.createNote; + +export const selectCreateNoteError = (state: State) => state.notes.error.createNote; + export const selectNotesByDocumentId = createSelector( [selectAllNotes, (state, documentId) => documentId], (notes, documentId) => notes.filter((note) => note.eventId === documentId) From 9fd2978fd7b80363807f12e211f642532dd224e2 Mon Sep 17 00:00:00 2001 From: Shahzad Date: Tue, 25 Jun 2024 16:19:50 +0200 Subject: [PATCH 05/22] [Observability ] Bundle optimization !!! (#186820) ## Summary Only code refactoring done !! image --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> --- packages/kbn-optimizer/limits.yml | 2 +- .../helpers/get_group.ts | 2 +- .../get_alert_search_bar_lazy.tsx | 2 +- .../components/rule_condition_chart/index.tsx | 19 +++++ .../rule_condition_chart.tsx | 5 +- .../autocomplete_field/autocomplete_field.tsx | 5 +- .../components/rule_kql_filter/index.tsx | 41 +++++++++ .../components/rule_kql_filter/kuery_bar.tsx | 7 +- .../with_kuery_autocompletion.tsx | 5 +- .../observability/public/index.ts | 19 ++--- .../components/alert_summary.tsx | 5 +- .../pages/alert_details/components/index.tsx | 19 +++++ .../components/date_picker/date_picker.tsx | 12 +-- .../overview/components/date_picker/index.tsx | 19 +++++ .../observability_rule_type_registry_mock.ts | 2 +- .../public/utils/kibana_react.ts | 2 +- .../observability/tsconfig.json | 1 - .../utils => slo/common}/parse_kuery.ts | 0 .../public/hooks/use_create_rule.ts | 13 ++- .../hooks/use_fetch_group_by_cardinality.ts | 2 +- .../components/common/use_table_docs.tsx | 2 +- .../components/slo_edit_form_footer.tsx | 2 +- .../public/pages/slo_edit/slo_edit.test.tsx | 4 +- .../translations/translations/fr-FR.json | 84 +++++++++---------- .../translations/translations/ja-JP.json | 84 +++++++++---------- .../translations/translations/zh-CN.json | 84 +++++++++---------- 26 files changed, 268 insertions(+), 174 deletions(-) create mode 100644 x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/index.tsx create mode 100644 x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx create mode 100644 x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/index.tsx create mode 100644 x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/index.tsx rename x-pack/plugins/observability_solution/{observability/common/utils => slo/common}/parse_kuery.ts (100%) rename x-pack/plugins/observability_solution/{observability => slo}/public/hooks/use_create_rule.ts (82%) diff --git a/packages/kbn-optimizer/limits.yml b/packages/kbn-optimizer/limits.yml index da7f526031534..c012f2f05879c 100644 --- a/packages/kbn-optimizer/limits.yml +++ b/packages/kbn-optimizer/limits.yml @@ -108,7 +108,7 @@ pageLoadAssetSize: navigation: 37269 newsfeed: 42228 noDataPage: 5000 - observability: 167673 + observability: 76678 observabilityAIAssistant: 58230 observabilityAIAssistantApp: 27680 observabilityAiAssistantManagement: 19279 diff --git a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_group.ts b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_group.ts index 67437421e4bad..e993c919c3368 100644 --- a/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_group.ts +++ b/x-pack/plugins/observability_solution/observability/common/custom_threshold_rule/helpers/get_group.ts @@ -7,7 +7,7 @@ import { Filter } from '@kbn/es-query'; import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; -import { Group } from '../../typings'; +import type { Group } from '../../typings'; /* * groupFieldName diff --git a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/get_alert_search_bar_lazy.tsx b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/get_alert_search_bar_lazy.tsx index 3cd1c1e88c353..433765c27adb2 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/get_alert_search_bar_lazy.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/alert_search_bar/get_alert_search_bar_lazy.tsx @@ -7,7 +7,7 @@ import React, { lazy, Suspense } from 'react'; import { EuiLoadingSpinner } from '@elastic/eui'; -import { ObservabilityAlertSearchBarProps } from './types'; +import type { ObservabilityAlertSearchBarProps } from './types'; const ObservabilityAlertSearchBarLazy = lazy(() => import('./alert_search_bar')); diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/index.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/index.tsx new file mode 100644 index 0000000000000..2b8a79401de70 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/index.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, { lazy, Suspense } from 'react'; +import type { RuleConditionChartProps } from './rule_condition_chart'; + +const RuleConditionChartLazy = lazy(() => import('./rule_condition_chart')); + +export function RuleConditionChart(props: RuleConditionChartProps) { + return ( + + + + ); +} diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/rule_condition_chart.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/rule_condition_chart.tsx index a8710004876ff..407637520dda7 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/rule_condition_chart.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/rule_condition_chart.tsx @@ -69,7 +69,7 @@ export interface RuleConditionChartExpressions { timeUnit?: TimeUnitChar; equation?: string; } -interface RuleConditionChartProps { +export interface RuleConditionChartProps { metricExpression: RuleConditionChartExpressions; searchConfiguration: GenericSearchSourceFields; dataView?: DataView; @@ -471,3 +471,6 @@ export function RuleConditionChart({ ); } + +// eslint-disable-next-line import/no-default-export +export default RuleConditionChart; diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx index e8545276c572a..61e56b6175838 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx @@ -21,7 +21,7 @@ function composeStateUpdaters(...updaters: Array updater(currentState, props) || currentState, state); } -interface AutocompleteFieldProps { +export interface AutocompleteFieldProps { isLoadingSuggestions: boolean; isValid: boolean; loadSuggestions: (value: string, cursorPosition: number, maxCount?: number) => void; @@ -330,3 +330,6 @@ const withUnfocused = (state: AutocompleteFieldState) => ({ ...state, isFocused: false, }); + +// eslint-disable-next-line import/no-default-export +export default AutocompleteField; diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx new file mode 100644 index 0000000000000..a7ed90f1a9f4d --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/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, { lazy, Suspense } from 'react'; +import type { WithKueryAutocompletionLifecycleProps } from './with_kuery_autocompletion'; +import type { AutocompleteFieldProps } from './autocomplete_field'; +import type { RuleFlyoutKueryBarProps } from './kuery_bar'; + +const RuleFlyoutKueryBarLazy = lazy(() => import('./kuery_bar')); + +export function RuleFlyoutKueryBar(props: RuleFlyoutKueryBarProps) { + return ( + + + + ); +} + +const AutocompleteFieldLazy = lazy(() => import('./autocomplete_field/autocomplete_field')); + +export function AutocompleteField(props: AutocompleteFieldProps) { + return ( + + + + ); +} + +const WithKueryAutocompletionLazy = lazy(() => import('./with_kuery_autocompletion')); + +export function WithKueryAutocompletion(props: WithKueryAutocompletionLifecycleProps) { + return ( + + + + ); +} diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx index 26115ec331021..1e8359da2aab6 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx @@ -22,7 +22,7 @@ type LoadSuggestionsFn = ( ) => void; export type CurryLoadSuggestionsType = (loadSuggestions: LoadSuggestionsFn) => LoadSuggestionsFn; -interface Props { +export interface RuleFlyoutKueryBarProps { derivedIndexPattern: DataViewBase; onSubmit: (query: string) => void; onChange?: (query: string) => void; @@ -49,7 +49,7 @@ export function RuleFlyoutKueryBar({ placeholder, curryLoadSuggestions = defaultCurryLoadSuggestions, compressed, -}: Props) { +}: RuleFlyoutKueryBarProps) { const [draftQuery, setDraftQuery] = useState(value || ''); const [isValid, setValidation] = useState(true); @@ -100,3 +100,6 @@ const defaultCurryLoadSuggestions: CurryLoadSuggestionsType = (loadSuggestions) => (...args) => loadSuggestions(...args); + +// eslint-disable-next-line import/no-default-export +export default RuleFlyoutKueryBar; diff --git a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/with_kuery_autocompletion.tsx b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/with_kuery_autocompletion.tsx index 2325434a08234..0d43abc758acb 100644 --- a/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/with_kuery_autocompletion.tsx +++ b/x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/with_kuery_autocompletion.tsx @@ -16,7 +16,7 @@ import type { DataView } from '@kbn/data-views-plugin/public'; import { QuerySuggestion } from '@kbn/unified-search-plugin/public'; import { InfraClientStartDeps, RendererFunction } from '../custom_threshold/types'; -interface WithKueryAutocompletionLifecycleProps { +export interface WithKueryAutocompletionLifecycleProps { kibana: KibanaReactContextValue; children: RendererFunction<{ isLoadingSuggestions: boolean; @@ -111,3 +111,6 @@ class WithKueryAutocompletionComponent extends React.Component< export const WithKueryAutocompletion = withKibana( WithKueryAutocompletionComponent ); + +// eslint-disable-next-line import/no-default-export +export default WithKueryAutocompletion; diff --git a/x-pack/plugins/observability_solution/observability/public/index.ts b/x-pack/plugins/observability_solution/observability/public/index.ts index 665bdeb0569b3..27b715a6d8f7e 100644 --- a/x-pack/plugins/observability_solution/observability/public/index.ts +++ b/x-pack/plugins/observability_solution/observability/public/index.ts @@ -57,14 +57,14 @@ export { export type { RulesParams } from './locators/rules'; export { getCoreVitalsComponent } from './pages/overview/components/sections/ux/core_web_vitals/get_core_web_vitals_lazy'; export { ObservabilityAlertSearchBar } from './components/alert_search_bar/get_alert_search_bar_lazy'; -export { DatePicker } from './pages/overview/components/date_picker/date_picker'; +export { DatePicker } from './pages/overview/components/date_picker'; export const LazyAlertsFlyout = lazy(() => import('./components/alerts_flyout/alerts_flyout')); export * from './typings'; import { TopAlert } from './typings/alerts'; -import { AlertSummary } from './pages/alert_details/components/alert_summary'; -import { AlertSummaryField } from './pages/alert_details/components/alert_summary'; +import { AlertSummary } from './pages/alert_details/components'; +import type { AlertSummaryField } from './pages/alert_details/components/alert_summary'; export type { TopAlert, AlertSummary, AlertSummaryField }; export { observabilityFeatureId, observabilityAppId } from '../common'; @@ -73,8 +73,6 @@ export { useFetchDataViews } from './hooks/use_fetch_data_views'; export { useTimeBuckets } from './hooks/use_time_buckets'; export { createUseRulesLink } from './hooks/create_use_rules_link'; export { useSummaryTimeRange } from './hooks/use_summary_time_range'; -export { useGetFilteredRuleTypes } from './hooks/use_get_filtered_rule_types'; -export { useCreateRule } from './hooks/use_create_rule'; export { getApmTraceUrl } from './utils/get_apm_trace_url'; export { buildEsQuery } from './utils/build_es_query'; @@ -94,11 +92,12 @@ export { calculateTimeRangeBucketSize } from './pages/overview/helpers/calculate export type { render } from './utils/test_helper'; export { convertTo } from '../common/utils/formatters/duration'; -export { getElasticsearchQueryOrThrow } from '../common/utils/parse_kuery'; export { formatAlertEvaluationValue } from './utils/format_alert_evaluation_value'; -export { WithKueryAutocompletion } from './components/rule_kql_filter/with_kuery_autocompletion'; -export { AutocompleteField } from './components/rule_kql_filter/autocomplete_field'; -export { RuleFlyoutKueryBar } from './components/rule_kql_filter/kuery_bar'; -export { RuleConditionChart } from './components/rule_condition_chart/rule_condition_chart'; +export { + RuleFlyoutKueryBar, + AutocompleteField, + WithKueryAutocompletion, +} from './components/rule_kql_filter'; +export { RuleConditionChart } from './components/rule_condition_chart'; export { getGroupFilters } from '../common/custom_threshold_rule/helpers/get_group'; export type { GenericAggType } from './components/rule_condition_chart/rule_condition_chart'; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx index 82c22626aab85..7738b27089a57 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx @@ -28,7 +28,7 @@ export interface AlertSummaryField { label: ReactNode | string; value: ReactNode | string | number; } -interface AlertSummaryProps { +export interface AlertSummaryProps { alert: TopAlert; alertSummaryFields?: AlertSummaryField[]; } @@ -110,3 +110,6 @@ export function AlertSummary({ alert, alertSummaryFields }: AlertSummaryProps) { ); } + +// eslint-disable-next-line import/no-default-export +export default AlertSummary; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/index.tsx b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/index.tsx new file mode 100644 index 0000000000000..8af473faab59d --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/index.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, { lazy, Suspense } from 'react'; +import type { AlertSummaryProps } from './alert_summary'; + +const AlertSummaryLazy = lazy(() => import('./alert_summary')); + +export function AlertSummary(props: AlertSummaryProps) { + return ( + + + + ); +} diff --git a/x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/date_picker.tsx b/x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/date_picker.tsx index e3bb21a460067..56ec220cbb940 100644 --- a/x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/date_picker.tsx +++ b/x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/date_picker.tsx @@ -16,17 +16,7 @@ export interface TimePickerQuickRange { display: string; } -export interface TimePickerRefreshInterval { - pause: boolean; - value: number; -} - -export interface TimePickerTimeDefaults { - from: string; - to: string; -} - -interface DatePickerProps { +export interface DatePickerProps { rangeFrom?: string; rangeTo?: string; refreshPaused?: boolean; diff --git a/x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/index.tsx b/x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/index.tsx new file mode 100644 index 0000000000000..033de0beff657 --- /dev/null +++ b/x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/index.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, { lazy, Suspense } from 'react'; +import type { DatePickerProps } from './date_picker'; + +const DatePickerLazy = lazy(() => import('./date_picker')); + +export function DatePicker(props: DatePickerProps) { + return ( + + + + ); +} diff --git a/x-pack/plugins/observability_solution/observability/public/rules/observability_rule_type_registry_mock.ts b/x-pack/plugins/observability_solution/observability/public/rules/observability_rule_type_registry_mock.ts index 4a2f8cfc3ba8c..30a6c6eda7149 100644 --- a/x-pack/plugins/observability_solution/observability/public/rules/observability_rule_type_registry_mock.ts +++ b/x-pack/plugins/observability_solution/observability/public/rules/observability_rule_type_registry_mock.ts @@ -5,7 +5,7 @@ * 2.0. */ -import { ObservabilityRuleTypeRegistry } from './create_observability_rule_type_registry'; +import type { ObservabilityRuleTypeRegistry } from './create_observability_rule_type_registry'; const createRuleTypeRegistryMock = () => ({ getFormatter: () => () => 'a reason', diff --git a/x-pack/plugins/observability_solution/observability/public/utils/kibana_react.ts b/x-pack/plugins/observability_solution/observability/public/utils/kibana_react.ts index 209e0ce4b2382..4797a76f0e535 100644 --- a/x-pack/plugins/observability_solution/observability/public/utils/kibana_react.ts +++ b/x-pack/plugins/observability_solution/observability/public/utils/kibana_react.ts @@ -8,7 +8,7 @@ import { CoreStart } from '@kbn/core/public'; import { useKibana } from '@kbn/kibana-react-plugin/public'; import { Storage } from '@kbn/kibana-utils-plugin/public'; -import { ObservabilityPublicPluginsStart } from '../plugin'; +import type { ObservabilityPublicPluginsStart } from '../plugin'; export type StartServices = CoreStart & ObservabilityPublicPluginsStart & diff --git a/x-pack/plugins/observability_solution/observability/tsconfig.json b/x-pack/plugins/observability_solution/observability/tsconfig.json index 84ef4bc7eee11..da98c7fc6494b 100644 --- a/x-pack/plugins/observability_solution/observability/tsconfig.json +++ b/x-pack/plugins/observability_solution/observability/tsconfig.json @@ -52,7 +52,6 @@ "@kbn/logging", "@kbn/share-plugin", "@kbn/core-notifications-browser", - "@kbn/slo-schema", "@kbn/guided-onboarding", "@kbn/charts-plugin", "@kbn/securitysolution-ecs", diff --git a/x-pack/plugins/observability_solution/observability/common/utils/parse_kuery.ts b/x-pack/plugins/observability_solution/slo/common/parse_kuery.ts similarity index 100% rename from x-pack/plugins/observability_solution/observability/common/utils/parse_kuery.ts rename to x-pack/plugins/observability_solution/slo/common/parse_kuery.ts diff --git a/x-pack/plugins/observability_solution/observability/public/hooks/use_create_rule.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_create_rule.ts similarity index 82% rename from x-pack/plugins/observability_solution/observability/public/hooks/use_create_rule.ts rename to x-pack/plugins/observability_solution/slo/public/hooks/use_create_rule.ts index 7c30544105aaa..04376e5299be3 100644 --- a/x-pack/plugins/observability_solution/observability/public/hooks/use_create_rule.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_create_rule.ts @@ -9,7 +9,7 @@ import { useMutation } from '@tanstack/react-query'; import { i18n } from '@kbn/i18n'; import { BASE_ALERTING_API_PATH, RuleTypeParams } from '@kbn/alerting-plugin/common'; import { v4 } from 'uuid'; -import { +import type { CreateRuleRequestBody, CreateRuleResponse, } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; @@ -41,7 +41,7 @@ export function useCreateRule() { { onError: (_err) => { toasts.addDanger( - i18n.translate('xpack.observability.rules.createRule.errorNotification.descriptionText', { + i18n.translate('xpack.slo.rules.createRule.errorNotification.descriptionText', { defaultMessage: 'Failed to create rule', }) ); @@ -49,12 +49,9 @@ export function useCreateRule() { onSuccess: () => { toasts.addSuccess( - i18n.translate( - 'xpack.observability.rules.createRule.successNotification.descriptionText', - { - defaultMessage: 'Rule created', - } - ) + i18n.translate('xpack.slo.rules.createRule.successNotification.descriptionText', { + defaultMessage: 'Rule created', + }) ); }, } diff --git a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_group_by_cardinality.ts b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_group_by_cardinality.ts index a5a193db672fb..6be95e67c0d89 100644 --- a/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_group_by_cardinality.ts +++ b/x-pack/plugins/observability_solution/slo/public/hooks/use_fetch_group_by_cardinality.ts @@ -9,7 +9,7 @@ import { debounce } from 'lodash'; import { ALL_VALUE, QuerySchema } from '@kbn/slo-schema'; import { useQuery } from '@tanstack/react-query'; import { lastValueFrom } from 'rxjs'; -import { getElasticsearchQueryOrThrow } from '@kbn/observability-plugin/public'; +import { getElasticsearchQueryOrThrow } from '../../common/parse_kuery'; import { useKibana } from '../utils/kibana_react'; export interface UseFetchGroupByCardinalityResponse { diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/common/use_table_docs.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/common/use_table_docs.tsx index d1b17b6747fa1..dc58571f58685 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/common/use_table_docs.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/common/use_table_docs.tsx @@ -10,7 +10,7 @@ import { FieldPath, useFormContext } from 'react-hook-form'; import { DataView } from '@kbn/data-views-plugin/common'; import { TimeRange } from '@kbn/es-query'; import { QuerySchema } from '@kbn/slo-schema'; -import { getElasticsearchQueryOrThrow } from '@kbn/observability-plugin/public'; +import { getElasticsearchQueryOrThrow } from '../../../../../common/parse_kuery'; import { CreateSLOForm } from '../../types'; export const useTableDocs = ({ diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/slo_edit_form_footer.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/slo_edit_form_footer.tsx index 267fd7f6d9851..f3f18c7f0b332 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/slo_edit_form_footer.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/components/slo_edit_form_footer.tsx @@ -11,7 +11,7 @@ import type { GetSLOResponse } from '@kbn/slo-schema'; import React, { useCallback, useMemo } from 'react'; import { useFormContext } from 'react-hook-form'; import { InPortal } from 'react-reverse-portal'; -import { useCreateRule } from '@kbn/observability-plugin/public'; +import { useCreateRule } from '../../../hooks/use_create_rule'; import { useKibana } from '../../../utils/kibana_react'; import { sloEditFormFooterPortal } from '../shared_flyout/slo_add_form_flyout'; import { paths } from '../../../../common/locators/paths'; diff --git a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.test.tsx b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.test.tsx index 03838225d1618..cd20c06c9d491 100644 --- a/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.test.tsx +++ b/x-pack/plugins/observability_solution/slo/public/pages/slo_edit/slo_edit.test.tsx @@ -8,7 +8,7 @@ import { ILicense } from '@kbn/licensing-plugin/common/types'; import { licensingMock } from '@kbn/licensing-plugin/public/mocks'; import { observabilityAIAssistantPluginMock } from '@kbn/observability-ai-assistant-plugin/public/mock'; -import { useCreateRule, useFetchDataViews } from '@kbn/observability-plugin/public'; +import { useFetchDataViews } from '@kbn/observability-plugin/public'; import { HeaderMenuPortal } from '@kbn/observability-shared-plugin/public'; import { cleanup, fireEvent, waitFor } from '@testing-library/react'; import { createBrowserHistory } from 'history'; @@ -23,6 +23,7 @@ import { useFetchApmSuggestions } from '../../hooks/use_fetch_apm_suggestions'; import { useFetchIndices } from '../../hooks/use_fetch_indices'; import { useFetchSloDetails } from '../../hooks/use_fetch_slo_details'; import { usePermissions } from '../../hooks/use_permissions'; +import { useCreateRule } from '../../hooks/use_create_rule'; import { useUpdateSlo } from '../../hooks/use_update_slo'; import { useKibana } from '../../utils/kibana_react'; import { kibanaStartMock } from '../../utils/kibana_react.mock'; @@ -44,6 +45,7 @@ jest.mock('../../hooks/use_create_slo'); jest.mock('../../hooks/use_update_slo'); jest.mock('../../hooks/use_fetch_apm_suggestions'); jest.mock('../../hooks/use_permissions'); +jest.mock('../../hooks/use_create_rule'); const mockUseKibanaReturnValue = kibanaStartMock.startContract(); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index f86ccb33528e8..1e2d0b57533ff 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -2396,12 +2396,7 @@ "discover.fieldChooser.discoverField.removeFieldTooltip": "Supprimer le champ du tableau", "discover.globalSearch.esqlSearchTitle": "Créer des recherches ES|QL", "discover.goToDiscoverButtonText": "Aller à Discover", - "unifiedDocViewer.flyout.documentNavigation": "Navigation dans le document", - "unifiedDocViewer.flyout.toastColumnAdded": "La colonne \"{columnName}\" a été ajoutée.", - "unifiedDocViewer.flyout.toastColumnRemoved": "La colonne \"{columnName}\" a été supprimée.", "discover.grid.tableRow.actionsLabel": "Actions", - "unifiedDocViewer.flyout.docViewerDetailHeading": "Document", - "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "Ligne", "discover.grid.tableRow.mobileFlyoutActionsButton": "Actions", "discover.grid.tableRow.moreFlyoutActionsButton": "Plus d'actions", "discover.grid.tableRow.esqlDetailHeading": "Ligne développée", @@ -2494,6 +2489,46 @@ "discover.viewAlert.searchSourceErrorTitle": "Erreur lors de la récupération de la source de recherche", "discover.viewModes.document.label": "Documents", "discover.viewModes.fieldStatistics.label": "Statistiques de champ", + "unifiedDocViewer.flyout.documentNavigation": "Navigation dans le document", + "unifiedDocViewer.flyout.toastColumnAdded": "La colonne \"{columnName}\" a été ajoutée.", + "unifiedDocViewer.flyout.toastColumnRemoved": "La colonne \"{columnName}\" a été supprimée.", + "unifiedDocViewer.flyout.docViewerDetailHeading": "Document", + "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "Ligne", + "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "Une ou plusieurs valeurs dans ce champ sont trop longues et ne peuvent pas être recherchées ni filtrées.", + "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "Ce champ comporte une ou plusieurs valeurs mal formées qui ne peuvent pas être recherchées ni filtrées.", + "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "Une ou plusieurs valeurs dans ce champ ont été ignorées par Elasticsearch et ne peuvent pas être recherchées ni filtrées.", + "unifiedDocViewer.docView.table.ignored.singleAboveTooltip": "La valeur dans ce champ est trop longue et ne peut pas être recherchée ni filtrée.", + "unifiedDocViewer.docView.table.ignored.singleMalformedTooltip": "La valeur dans ce champ est mal formée et ne peut pas être recherchée ni filtrée.", + "unifiedDocViewer.docView.table.ignored.singleUnknownTooltip": "La valeur dans ce champ a été ignorée par Elasticsearch et ne peut pas être recherchée ni filtrée.", + "unifiedDocViewer.docView.table.searchPlaceHolder": "Rechercher les noms de champs", + "unifiedDocViewer.docViews.json.jsonTitle": "JSON", + "unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel": "Filtrer sur le champ", + "unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip": "Filtrer sur le champ", + "unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel": "Filtrer sur la valeur", + "unifiedDocViewer.docViews.table.filterForValueButtonTooltip": "Filtrer sur la valeur", + "unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel": "Exclure la valeur", + "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "Exclure la valeur", + "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "Contient des valeurs ignorées", + "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "Valeur ignorée", + "unifiedDocViewer.docViews.table.pinFieldLabel": "Épingler le champ", + "unifiedDocViewer.docViews.table.tableTitle": "Tableau", + "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "Afficher/Masquer la colonne dans le tableau", + "unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip": "Afficher/Masquer la colonne dans le tableau", + "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "Impossible de filtrer sur les champs méta", + "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "Impossible de filtrer sur les champs scriptés", + "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "Les champs non indexés ou les valeurs ignorées ne peuvent pas être recherchés", + "unifiedDocViewer.docViews.table.unpinFieldLabel": "Désépingler le champ", + "unifiedDocViewer.fieldChooser.discoverField.actions": "Actions", + "unifiedDocViewer.fieldChooser.discoverField.multiField": "champ multiple", + "unifiedDocViewer.fieldChooser.discoverField.multiFieldTooltipContent": "Les champs multiples peuvent avoir plusieurs valeurs.", + "unifiedDocViewer.fieldChooser.discoverField.name": "Champ", + "unifiedDocViewer.fieldChooser.discoverField.value": "Valeur", + "unifiedDocViewer.json.codeEditorAriaLabel": "Affichage JSON en lecture seule d’un document Elasticsearch", + "unifiedDocViewer.json.copyToClipboardLabel": "Copier dans le presse-papiers", + "unifiedDocViewer.loadingJSON": "Chargement de JSON", + "unifiedDocViewer.sourceViewer.errorMessage": "Impossible de récupérer les données pour le moment. Actualisez l'onglet et réessayez.", + "unifiedDocViewer.sourceViewer.errorMessageTitle": "Une erreur s'est produite.", + "unifiedDocViewer.sourceViewer.refresh": "Actualiser", "textBasedLanguages.advancedSettings.enableESQL.discussLinkText": "discuss.elastic.co/c/elastic-stack/kibana", "textBasedLanguages.advancedSettings.enableESQLTitle": "Activer ES|QL", "domDragDrop.announce.cancelled": "Mouvement annulé. {label} revenu à sa position initiale", @@ -29937,8 +29972,6 @@ "xpack.observability.rulePage.logsTabTitle": "Logs", "xpack.observability.rulePage.rulesTabTitle": "Règles", "xpack.observability.rules.addRuleButtonLabel": "Créer une règle", - "xpack.observability.rules.createRule.errorNotification.descriptionText": "Échec de création de la règle", - "xpack.observability.rules.createRule.successNotification.descriptionText": "Règle créée", "xpack.observability.rules.deleteConfirmationModal.cancelButtonLabel": "Annuler", "xpack.observability.rules.deleteConfirmationModal.errorNotification.descriptionText": "Impossible de supprimer la règle", "xpack.observability.rules.deleteConfirmationModal.successNotification.descriptionText": "Règle supprimée", @@ -44202,41 +44235,6 @@ "uiActions.errors.incompatibleAction": "Action non compatible", "uiActions.triggers.rowClickkDescription": "Un clic sur une ligne de tableau", "uiActions.triggers.rowClickTitle": "Clic sur ligne de tableau", - "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "Une ou plusieurs valeurs dans ce champ sont trop longues et ne peuvent pas être recherchées ni filtrées.", - "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "Ce champ comporte une ou plusieurs valeurs mal formées qui ne peuvent pas être recherchées ni filtrées.", - "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "Une ou plusieurs valeurs dans ce champ ont été ignorées par Elasticsearch et ne peuvent pas être recherchées ni filtrées.", - "unifiedDocViewer.docView.table.ignored.singleAboveTooltip": "La valeur dans ce champ est trop longue et ne peut pas être recherchée ni filtrée.", - "unifiedDocViewer.docView.table.ignored.singleMalformedTooltip": "La valeur dans ce champ est mal formée et ne peut pas être recherchée ni filtrée.", - "unifiedDocViewer.docView.table.ignored.singleUnknownTooltip": "La valeur dans ce champ a été ignorée par Elasticsearch et ne peut pas être recherchée ni filtrée.", - "unifiedDocViewer.docView.table.searchPlaceHolder": "Rechercher les noms de champs", - "unifiedDocViewer.docViews.json.jsonTitle": "JSON", - "unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel": "Filtrer sur le champ", - "unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip": "Filtrer sur le champ", - "unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel": "Filtrer sur la valeur", - "unifiedDocViewer.docViews.table.filterForValueButtonTooltip": "Filtrer sur la valeur", - "unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel": "Exclure la valeur", - "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "Exclure la valeur", - "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "Contient des valeurs ignorées", - "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "Valeur ignorée", - "unifiedDocViewer.docViews.table.pinFieldLabel": "Épingler le champ", - "unifiedDocViewer.docViews.table.tableTitle": "Tableau", - "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "Afficher/Masquer la colonne dans le tableau", - "unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip": "Afficher/Masquer la colonne dans le tableau", - "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "Impossible de filtrer sur les champs méta", - "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "Impossible de filtrer sur les champs scriptés", - "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "Les champs non indexés ou les valeurs ignorées ne peuvent pas être recherchés", - "unifiedDocViewer.docViews.table.unpinFieldLabel": "Désépingler le champ", - "unifiedDocViewer.fieldChooser.discoverField.actions": "Actions", - "unifiedDocViewer.fieldChooser.discoverField.multiField": "champ multiple", - "unifiedDocViewer.fieldChooser.discoverField.multiFieldTooltipContent": "Les champs multiples peuvent avoir plusieurs valeurs.", - "unifiedDocViewer.fieldChooser.discoverField.name": "Champ", - "unifiedDocViewer.fieldChooser.discoverField.value": "Valeur", - "unifiedDocViewer.json.codeEditorAriaLabel": "Affichage JSON en lecture seule d’un document Elasticsearch", - "unifiedDocViewer.json.copyToClipboardLabel": "Copier dans le presse-papiers", - "unifiedDocViewer.loadingJSON": "Chargement de JSON", - "unifiedDocViewer.sourceViewer.errorMessage": "Impossible de récupérer les données pour le moment. Actualisez l'onglet et réessayez.", - "unifiedDocViewer.sourceViewer.errorMessageTitle": "Une erreur s'est produite.", - "unifiedDocViewer.sourceViewer.refresh": "Actualiser", "unsavedChangesBadge.contextMenu.openButton": "Afficher les actions disponibles", "unsavedChangesBadge.contextMenu.revertChangesButton": "Restaurer les modifications", "unsavedChangesBadge.contextMenu.revertingChangesButtonStatus": "Annuler les modifications", @@ -44589,4 +44587,4 @@ "xpack.serverlessObservability.nav.projectSettings": "Paramètres de projet", "xpack.serverlessObservability.nav.synthetics": "Synthetics" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index f5aa8a39a90b2..305baf56ccc5c 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -2393,12 +2393,7 @@ "discover.fieldChooser.discoverField.removeFieldTooltip": "フィールドを表から削除", "discover.globalSearch.esqlSearchTitle": "ES|QLクエリを作成", "discover.goToDiscoverButtonText": "Discoverに移動", - "unifiedDocViewer.flyout.documentNavigation": "ドキュメントナビゲーション", - "unifiedDocViewer.flyout.toastColumnAdded": "列'{columnName}'が追加されました", - "unifiedDocViewer.flyout.toastColumnRemoved": "列'{columnName}'が削除されました", "discover.grid.tableRow.actionsLabel": "アクション", - "unifiedDocViewer.flyout.docViewerDetailHeading": "ドキュメント", - "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "行", "discover.grid.tableRow.mobileFlyoutActionsButton": "アクション", "discover.grid.tableRow.moreFlyoutActionsButton": "さらにアクションを表示", "discover.grid.tableRow.esqlDetailHeading": "展開された行", @@ -2491,6 +2486,46 @@ "discover.viewAlert.searchSourceErrorTitle": "検索ソースの取得エラー", "discover.viewModes.document.label": "ドキュメント", "discover.viewModes.fieldStatistics.label": "フィールド統計情報", + "unifiedDocViewer.flyout.documentNavigation": "ドキュメントナビゲーション", + "unifiedDocViewer.flyout.toastColumnAdded": "列'{columnName}'が追加されました", + "unifiedDocViewer.flyout.toastColumnRemoved": "列'{columnName}'が削除されました", + "unifiedDocViewer.flyout.docViewerDetailHeading": "ドキュメント", + "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "行", + "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "このフィールドの1つ以上の値が長すぎるため、検索またはフィルタリングできません。", + "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "このフィールドは、検索またはフィルタリングできない正しくない形式の値が1つ以上あります。", + "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "このフィールドの1つ以上の値がElasticsearchによって無視されたため、検索またはフィルタリングできません。", + "unifiedDocViewer.docView.table.ignored.singleAboveTooltip": "このフィールドの値が長すぎるため、検索またはフィルタリングできません。", + "unifiedDocViewer.docView.table.ignored.singleMalformedTooltip": "このフィールドの値の形式が正しくないため、検索またはフィルタリングできません。", + "unifiedDocViewer.docView.table.ignored.singleUnknownTooltip": "このフィールドの値はElasticsearchによって無視されたため、検索またはフィルタリングできません。", + "unifiedDocViewer.docView.table.searchPlaceHolder": "検索フィールド名", + "unifiedDocViewer.docViews.json.jsonTitle": "JSON", + "unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel": "フィールド表示のフィルター", + "unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip": "フィールド表示のフィルター", + "unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel": "値でフィルター", + "unifiedDocViewer.docViews.table.filterForValueButtonTooltip": "値でフィルター", + "unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel": "値を除外", + "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "値を除外", + "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "無視された値を含む", + "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "無視された値", + "unifiedDocViewer.docViews.table.pinFieldLabel": "フィールドを固定", + "unifiedDocViewer.docViews.table.tableTitle": "表", + "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "表の列を切り替える", + "unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip": "表の列を切り替える", + "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "メタフィールドの有無でフィルタリングできません", + "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "スクリプトフィールドの有無でフィルタリングできません", + "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "インデックスがないフィールドまたは無視された値は検索できません", + "unifiedDocViewer.docViews.table.unpinFieldLabel": "フィールドを固定解除", + "unifiedDocViewer.fieldChooser.discoverField.actions": "アクション", + "unifiedDocViewer.fieldChooser.discoverField.multiField": "複数フィールド", + "unifiedDocViewer.fieldChooser.discoverField.multiFieldTooltipContent": "複数フィールドにはフィールドごとに複数の値を入力できます", + "unifiedDocViewer.fieldChooser.discoverField.name": "フィールド", + "unifiedDocViewer.fieldChooser.discoverField.value": "値", + "unifiedDocViewer.json.codeEditorAriaLabel": "Elasticsearch ドキュメントの JSON ビューのみを読み込む", + "unifiedDocViewer.json.copyToClipboardLabel": "クリップボードにコピー", + "unifiedDocViewer.loadingJSON": "JSONを読み込んでいます", + "unifiedDocViewer.sourceViewer.errorMessage": "現在データを取得できませんでした。タブを更新して、再試行してください。", + "unifiedDocViewer.sourceViewer.errorMessageTitle": "エラーが発生しました", + "unifiedDocViewer.sourceViewer.refresh": "更新", "textBasedLanguages.advancedSettings.enableESQL.discussLinkText": "discuss.elastic.co/c/elastic-stack/kibana", "textBasedLanguages.advancedSettings.enableESQLTitle": "ES|QLを有効化", "domDragDrop.announce.cancelled": "移動がキャンセルされました。{label}は初期位置に戻りました", @@ -29915,8 +29950,6 @@ "xpack.observability.rulePage.logsTabTitle": "ログ", "xpack.observability.rulePage.rulesTabTitle": "ルール", "xpack.observability.rules.addRuleButtonLabel": "ルールを作成", - "xpack.observability.rules.createRule.errorNotification.descriptionText": "ルールの作成に失敗しました", - "xpack.observability.rules.createRule.successNotification.descriptionText": "ルールが作成されました", "xpack.observability.rules.deleteConfirmationModal.cancelButtonLabel": "キャンセル", "xpack.observability.rules.deleteConfirmationModal.errorNotification.descriptionText": "ルールを削除できませんでした", "xpack.observability.rules.deleteConfirmationModal.successNotification.descriptionText": "削除されたルール", @@ -44178,41 +44211,6 @@ "uiActions.errors.incompatibleAction": "操作に互換性がありません", "uiActions.triggers.rowClickkDescription": "テーブル行をクリック", "uiActions.triggers.rowClickTitle": "テーブル行クリック", - "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "このフィールドの1つ以上の値が長すぎるため、検索またはフィルタリングできません。", - "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "このフィールドは、検索またはフィルタリングできない正しくない形式の値が1つ以上あります。", - "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "このフィールドの1つ以上の値がElasticsearchによって無視されたため、検索またはフィルタリングできません。", - "unifiedDocViewer.docView.table.ignored.singleAboveTooltip": "このフィールドの値が長すぎるため、検索またはフィルタリングできません。", - "unifiedDocViewer.docView.table.ignored.singleMalformedTooltip": "このフィールドの値の形式が正しくないため、検索またはフィルタリングできません。", - "unifiedDocViewer.docView.table.ignored.singleUnknownTooltip": "このフィールドの値はElasticsearchによって無視されたため、検索またはフィルタリングできません。", - "unifiedDocViewer.docView.table.searchPlaceHolder": "検索フィールド名", - "unifiedDocViewer.docViews.json.jsonTitle": "JSON", - "unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel": "フィールド表示のフィルター", - "unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip": "フィールド表示のフィルター", - "unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel": "値でフィルター", - "unifiedDocViewer.docViews.table.filterForValueButtonTooltip": "値でフィルター", - "unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel": "値を除外", - "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "値を除外", - "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "無視された値を含む", - "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "無視された値", - "unifiedDocViewer.docViews.table.pinFieldLabel": "フィールドを固定", - "unifiedDocViewer.docViews.table.tableTitle": "表", - "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "表の列を切り替える", - "unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip": "表の列を切り替える", - "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "メタフィールドの有無でフィルタリングできません", - "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "スクリプトフィールドの有無でフィルタリングできません", - "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "インデックスがないフィールドまたは無視された値は検索できません", - "unifiedDocViewer.docViews.table.unpinFieldLabel": "フィールドを固定解除", - "unifiedDocViewer.fieldChooser.discoverField.actions": "アクション", - "unifiedDocViewer.fieldChooser.discoverField.multiField": "複数フィールド", - "unifiedDocViewer.fieldChooser.discoverField.multiFieldTooltipContent": "複数フィールドにはフィールドごとに複数の値を入力できます", - "unifiedDocViewer.fieldChooser.discoverField.name": "フィールド", - "unifiedDocViewer.fieldChooser.discoverField.value": "値", - "unifiedDocViewer.json.codeEditorAriaLabel": "Elasticsearch ドキュメントの JSON ビューのみを読み込む", - "unifiedDocViewer.json.copyToClipboardLabel": "クリップボードにコピー", - "unifiedDocViewer.loadingJSON": "JSONを読み込んでいます", - "unifiedDocViewer.sourceViewer.errorMessage": "現在データを取得できませんでした。タブを更新して、再試行してください。", - "unifiedDocViewer.sourceViewer.errorMessageTitle": "エラーが発生しました", - "unifiedDocViewer.sourceViewer.refresh": "更新", "unsavedChangesBadge.contextMenu.openButton": "使用可能なアクションを表示", "unsavedChangesBadge.contextMenu.revertChangesButton": "変更を元に戻す", "unsavedChangesBadge.contextMenu.revertingChangesButtonStatus": "変更を元に戻しています...", @@ -44565,4 +44563,4 @@ "xpack.serverlessObservability.nav.projectSettings": "プロジェクト設定", "xpack.serverlessObservability.nav.synthetics": "Synthetics" } -} \ No newline at end of file +} diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 9b8a8910bc990..49bc0b78a8638 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -2397,12 +2397,7 @@ "discover.fieldChooser.discoverField.removeFieldTooltip": "从表中移除字段", "discover.globalSearch.esqlSearchTitle": "创建 ES|QL 查询", "discover.goToDiscoverButtonText": "前往 Discover", - "unifiedDocViewer.flyout.documentNavigation": "文档导航", - "unifiedDocViewer.flyout.toastColumnAdded": "已添加列“{columnName}”", - "unifiedDocViewer.flyout.toastColumnRemoved": "已移除列“{columnName}”", "discover.grid.tableRow.actionsLabel": "操作", - "unifiedDocViewer.flyout.docViewerDetailHeading": "文档", - "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "行", "discover.grid.tableRow.mobileFlyoutActionsButton": "操作", "discover.grid.tableRow.moreFlyoutActionsButton": "更多操作", "discover.grid.tableRow.esqlDetailHeading": "已展开行", @@ -2495,6 +2490,46 @@ "discover.viewAlert.searchSourceErrorTitle": "提取搜索源时出错", "discover.viewModes.document.label": "文档", "discover.viewModes.fieldStatistics.label": "字段统计信息", + "unifiedDocViewer.flyout.documentNavigation": "文档导航", + "unifiedDocViewer.flyout.toastColumnAdded": "已添加列“{columnName}”", + "unifiedDocViewer.flyout.toastColumnRemoved": "已移除列“{columnName}”", + "unifiedDocViewer.flyout.docViewerDetailHeading": "文档", + "unifiedDocViewer.flyout.docViewerEsqlDetailHeading": "行", + "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "此字段中的一个或多个值过长,无法搜索或筛选。", + "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "此字段包含一个或多个格式错误的值,无法搜索或筛选。", + "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "此字段中的一个或多个值被 Elasticsearch 忽略,无法搜索或筛选。", + "unifiedDocViewer.docView.table.ignored.singleAboveTooltip": "此字段中的值过长,无法搜索或筛选。", + "unifiedDocViewer.docView.table.ignored.singleMalformedTooltip": "此字段中的值格式错误,无法搜索或筛选。", + "unifiedDocViewer.docView.table.ignored.singleUnknownTooltip": "此字段中的值被 Elasticsearch 忽略,无法搜索或筛选。", + "unifiedDocViewer.docView.table.searchPlaceHolder": "搜索字段名称", + "unifiedDocViewer.docViews.json.jsonTitle": "JSON", + "unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel": "筛留存在的字段", + "unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip": "字段是否存在筛选", + "unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel": "筛留值", + "unifiedDocViewer.docViews.table.filterForValueButtonTooltip": "筛留值", + "unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel": "筛除值", + "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "筛除值", + "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "包含被忽略的值", + "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "被忽略的值", + "unifiedDocViewer.docViews.table.pinFieldLabel": "固定字段", + "unifiedDocViewer.docViews.table.tableTitle": "表", + "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "在表中切换列", + "unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip": "在表中切换列", + "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "无法筛选元数据字段是否存在", + "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "无法筛选脚本字段是否存在", + "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "无法搜索未编入索引的字段或被忽略的值", + "unifiedDocViewer.docViews.table.unpinFieldLabel": "取消固定字段", + "unifiedDocViewer.fieldChooser.discoverField.actions": "操作", + "unifiedDocViewer.fieldChooser.discoverField.multiField": "多字段", + "unifiedDocViewer.fieldChooser.discoverField.multiFieldTooltipContent": "多字段的每个字段可以有多个值", + "unifiedDocViewer.fieldChooser.discoverField.name": "字段", + "unifiedDocViewer.fieldChooser.discoverField.value": "值", + "unifiedDocViewer.json.codeEditorAriaLabel": "Elasticsearch 文档的只读 JSON 视图", + "unifiedDocViewer.json.copyToClipboardLabel": "复制到剪贴板", + "unifiedDocViewer.loadingJSON": "正在加载 JSON", + "unifiedDocViewer.sourceViewer.errorMessage": "当前无法获取数据。请刷新选项卡以重试。", + "unifiedDocViewer.sourceViewer.errorMessageTitle": "发生错误", + "unifiedDocViewer.sourceViewer.refresh": "刷新", "textBasedLanguages.advancedSettings.enableESQL.discussLinkText": "discuss.elastic.co/c/elastic-stack/kibana", "textBasedLanguages.advancedSettings.enableESQLTitle": "启用 ES|QL", "domDragDrop.announce.cancelled": "移动已取消。{label} 将返回至其初始位置", @@ -29955,8 +29990,6 @@ "xpack.observability.rulePage.logsTabTitle": "日志", "xpack.observability.rulePage.rulesTabTitle": "规则", "xpack.observability.rules.addRuleButtonLabel": "创建规则", - "xpack.observability.rules.createRule.errorNotification.descriptionText": "无法创建规则", - "xpack.observability.rules.createRule.successNotification.descriptionText": "已创建规则", "xpack.observability.rules.deleteConfirmationModal.cancelButtonLabel": "取消", "xpack.observability.rules.deleteConfirmationModal.errorNotification.descriptionText": "无法删除规则", "xpack.observability.rules.deleteConfirmationModal.successNotification.descriptionText": "已删除规则", @@ -44226,41 +44259,6 @@ "uiActions.errors.incompatibleAction": "操作不兼容", "uiActions.triggers.rowClickkDescription": "表格行的单击", "uiActions.triggers.rowClickTitle": "表格行单击", - "unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "此字段中的一个或多个值过长,无法搜索或筛选。", - "unifiedDocViewer.docView.table.ignored.multiMalformedTooltip": "此字段包含一个或多个格式错误的值,无法搜索或筛选。", - "unifiedDocViewer.docView.table.ignored.multiUnknownTooltip": "此字段中的一个或多个值被 Elasticsearch 忽略,无法搜索或筛选。", - "unifiedDocViewer.docView.table.ignored.singleAboveTooltip": "此字段中的值过长,无法搜索或筛选。", - "unifiedDocViewer.docView.table.ignored.singleMalformedTooltip": "此字段中的值格式错误,无法搜索或筛选。", - "unifiedDocViewer.docView.table.ignored.singleUnknownTooltip": "此字段中的值被 Elasticsearch 忽略,无法搜索或筛选。", - "unifiedDocViewer.docView.table.searchPlaceHolder": "搜索字段名称", - "unifiedDocViewer.docViews.json.jsonTitle": "JSON", - "unifiedDocViewer.docViews.table.filterForFieldPresentButtonAriaLabel": "筛留存在的字段", - "unifiedDocViewer.docViews.table.filterForFieldPresentButtonTooltip": "字段是否存在筛选", - "unifiedDocViewer.docViews.table.filterForValueButtonAriaLabel": "筛留值", - "unifiedDocViewer.docViews.table.filterForValueButtonTooltip": "筛留值", - "unifiedDocViewer.docViews.table.filterOutValueButtonAriaLabel": "筛除值", - "unifiedDocViewer.docViews.table.filterOutValueButtonTooltip": "筛除值", - "unifiedDocViewer.docViews.table.ignored.multiValueLabel": "包含被忽略的值", - "unifiedDocViewer.docViews.table.ignored.singleValueLabel": "被忽略的值", - "unifiedDocViewer.docViews.table.pinFieldLabel": "固定字段", - "unifiedDocViewer.docViews.table.tableTitle": "表", - "unifiedDocViewer.docViews.table.toggleColumnInTableButtonAriaLabel": "在表中切换列", - "unifiedDocViewer.docViews.table.toggleColumnInTableButtonTooltip": "在表中切换列", - "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfMetaFieldsTooltip": "无法筛选元数据字段是否存在", - "unifiedDocViewer.docViews.table.unableToFilterForPresenceOfScriptedFieldsTooltip": "无法筛选脚本字段是否存在", - "unifiedDocViewer.docViews.table.unindexedFieldsCanNotBeSearchedTooltip": "无法搜索未编入索引的字段或被忽略的值", - "unifiedDocViewer.docViews.table.unpinFieldLabel": "取消固定字段", - "unifiedDocViewer.fieldChooser.discoverField.actions": "操作", - "unifiedDocViewer.fieldChooser.discoverField.multiField": "多字段", - "unifiedDocViewer.fieldChooser.discoverField.multiFieldTooltipContent": "多字段的每个字段可以有多个值", - "unifiedDocViewer.fieldChooser.discoverField.name": "字段", - "unifiedDocViewer.fieldChooser.discoverField.value": "值", - "unifiedDocViewer.json.codeEditorAriaLabel": "Elasticsearch 文档的只读 JSON 视图", - "unifiedDocViewer.json.copyToClipboardLabel": "复制到剪贴板", - "unifiedDocViewer.loadingJSON": "正在加载 JSON", - "unifiedDocViewer.sourceViewer.errorMessage": "当前无法获取数据。请刷新选项卡以重试。", - "unifiedDocViewer.sourceViewer.errorMessageTitle": "发生错误", - "unifiedDocViewer.sourceViewer.refresh": "刷新", "unsavedChangesBadge.contextMenu.openButton": "查看可用操作", "unsavedChangesBadge.contextMenu.revertChangesButton": "恢复更改", "unsavedChangesBadge.contextMenu.revertingChangesButtonStatus": "正在恢复更改......", @@ -44613,4 +44611,4 @@ "xpack.serverlessObservability.nav.projectSettings": "项目设置", "xpack.serverlessObservability.nav.synthetics": "Synthetics" } -} \ No newline at end of file +} From 8e76b0b113089c793e4dba77610f90540ec9b8da Mon Sep 17 00:00:00 2001 From: James Gowdy Date: Tue, 25 Jun 2024 16:23:25 +0100 Subject: [PATCH 06/22] [ML] Fixing issue with empty object creation (#186821) Using `Object.create(null)` when creating objects for the anomaly results table. --- .../build_anomaly_table_items.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js b/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js index 306f04c7ca95c..8ffe9fb71bcdb 100644 --- a/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js +++ b/x-pack/plugins/ml/server/models/results_service/build_anomaly_table_items.js @@ -125,7 +125,7 @@ function aggregateAnomalies(anomalyRecords, interval, dateFormatTz) { return []; } - const aggregatedData = {}; + const aggregatedData = Object.create(null); anomalyRecords.forEach((record) => { // Use moment.js to get start of interval. const roundedTime = @@ -133,27 +133,32 @@ function aggregateAnomalies(anomalyRecords, interval, dateFormatTz) { ? moment(record.timestamp).tz(dateFormatTz).startOf(interval).valueOf() : moment(record.timestamp).startOf(interval).valueOf(); if (aggregatedData[roundedTime] === undefined) { - aggregatedData[roundedTime] = {}; + aggregatedData[roundedTime] = Object.create(null); } // Aggregate by job, then detectorIndex. const jobId = record.job_id; const jobsAtTime = aggregatedData[roundedTime]; - if (jobsAtTime[jobId] === undefined) { - jobsAtTime[jobId] = {}; + if (jobsAtTime[jobId] === undefined || Object.hasOwn(jobsAtTime, jobId) === false) { + jobsAtTime[jobId] = Object.create(null); } // Aggregate by detector - default to function_description if no description available. const detectorIndex = record.detector_index; + if (typeof detectorIndex !== 'number') { + return; + } const detectorsForJob = jobsAtTime[jobId]; if (detectorsForJob[detectorIndex] === undefined) { - detectorsForJob[detectorIndex] = {}; + detectorsForJob[detectorIndex] = Object.create(null); } // Now add an object for the anomaly with the highest anomaly score per entity. // For the choice of entity, look in order for byField, overField, partitionField. // If no by/over/partition, default to an empty String. - const entitiesForDetector = detectorsForJob[detectorIndex]; + const entitiesForDetector = Object.hasOwn(detectorsForJob, detectorIndex) + ? detectorsForJob[detectorIndex] + : Object.create(null); // TODO - are we worried about different byFields having the same // value e.g. host=server1 and machine=server1? @@ -163,7 +168,7 @@ function aggregateAnomalies(anomalyRecords, interval, dateFormatTz) { } if (entitiesForDetector[entity] === undefined) { entitiesForDetector[entity] = record; - } else { + } else if (Object.hasOwn(entitiesForDetector, entity)) { if (record.record_score > entitiesForDetector[entity].record_score) { entitiesForDetector[entity] = record; } From 48c0e0dd7c48e99cdd3bac98ac1d9b7d6a2beaa4 Mon Sep 17 00:00:00 2001 From: Steph Milovic Date: Tue, 25 Jun 2024 09:43:39 -0600 Subject: [PATCH 07/22] [Security solution] Attack discovery background task and persistence (#184949) --- .../cancel_attack_discovery_route.gen.ts | 34 ++ .../cancel_attack_discovery_route.schema.yaml | 41 ++ .../attack_discovery/common_attributes.gen.ts | 199 +++++++ .../common_attributes.schema.yaml | 197 +++++++ .../get_attack_discovery_route.gen.ts | 38 ++ .../get_attack_discovery_route.schema.yaml | 48 ++ .../post_attack_discovery_route.gen.ts | 51 +- .../post_attack_discovery_route.schema.yaml | 63 +-- .../conversations/common_attributes.gen.ts | 4 +- .../common_attributes.schema.yaml | 4 +- .../impl/schemas/index.ts | 3 + .../elastic_assistant/common/constants.ts | 2 + .../__mocks__/attack_discovery_schema.mock.ts | 128 +++++ .../server/__mocks__/data_clients.mock.ts | 19 + .../server/__mocks__/request.ts | 30 +- .../server/__mocks__/request_context.ts | 12 +- .../server/__mocks__/response.ts | 10 + .../create_attack_discovery.test.ts | 77 +++ .../create_attack_discovery.ts | 107 ++++ .../field_maps_configuration.ts | 181 +++++++ ...d_attack_discovery_by_connector_id.test.ts | 69 +++ .../find_attack_discovery_by_connector_id.ts | 78 +++ .../get_attack_discovery.test.ts | 67 +++ .../attack_discovery/get_attack_discovery.ts | 78 +++ .../attack_discovery/index.ts | 122 +++++ .../attack_discovery/transforms.ts | 65 +++ .../attack_discovery/types.ts | 76 +++ .../update_attack_discovery.test.ts | 183 +++++++ .../update_attack_discovery.ts | 155 ++++++ .../server/ai_assistant_service/index.test.ts | 47 +- .../server/ai_assistant_service/index.ts | 44 +- .../lib/telemetry/event_based_telemetry.ts | 112 ++++ .../cancel_attack_discovery.test.ts | 107 ++++ .../cancel_attack_discovery.ts | 92 ++++ .../get_attack_discovery.test.ts | 116 +++++ .../attack_discovery/get_attack_discovery.ts | 92 ++++ .../routes/attack_discovery/helpers.test.ts | 491 ++++++++++++++++++ .../server/routes/attack_discovery/helpers.ts | 343 +++++++++++- .../post_attack_discovery.test.ts | 142 +++++ .../attack_discovery/post_attack_discovery.ts | 116 +++-- .../elastic_assistant/server/routes/index.ts | 1 + .../server/routes/register_routes.ts | 4 + .../server/routes/request_context_factory.ts | 9 + .../plugins/elastic_assistant/server/types.ts | 6 + .../plugins/elastic_assistant/tsconfig.json | 1 + .../attack/attack_chain/index.tsx | 2 +- .../attack/mini_attack_chain/index.tsx | 2 +- .../actionable_summary/index.tsx | 3 +- .../attack_discovery_panel/actions/index.tsx | 3 +- .../actions/take_action/index.tsx | 3 +- .../attack_discovery_panel/index.tsx | 3 +- .../interval/helpers.ts | 28 - .../tabs/alerts_tab/index.tsx | 3 +- .../tabs/attack_discovery_tab/index.tsx | 3 +- .../attack_discovery_panel/tabs/get_tabs.tsx | 3 +- .../attack_discovery_panel/tabs/index.tsx | 3 +- .../view_in_ai_assistant/index.tsx | 3 +- .../use_view_in_ai_assistant.ts | 5 +- .../get_attack_discovery_markdown.ts | 3 +- .../public/attack_discovery/helpers.ts | 2 +- .../index.test.tsx | 59 --- .../use_attack_discovery_telemetry/index.tsx | 23 - .../hooks/use_poll_api.test.tsx | 197 +++++++ .../attack_discovery/hooks/use_poll_api.tsx | 180 +++++++ .../mock/mock_use_attack_discovery.ts | 401 ++------------ .../pages/empty_states/index.test.tsx | 66 +++ .../pages/empty_states/index.tsx | 5 + .../pages/failure/index.test.tsx | 53 ++ .../attack_discovery/pages/failure/index.tsx | 43 ++ .../pages/failure/translations.ts | 22 + .../attack_discovery/pages/header/index.tsx | 48 +- .../pages/header/translations.ts | 6 +- .../attack_discovery/pages/index.test.tsx | 3 + .../public/attack_discovery/pages/index.tsx | 170 +++--- .../pages/loading_callout/countdown/index.tsx | 22 +- .../generation_timing/index.tsx | 5 +- .../countdown/last_times_popover/helpers.ts | 2 +- .../countdown/last_times_popover/index.tsx | 2 +- .../pages/loading_callout/index.tsx | 2 +- .../info_popover_body/index.tsx | 2 +- .../pages/session_storage/index.test.ts | 180 ------- .../pages/session_storage/index.ts | 120 ----- .../attack_discovery/pages/translations.ts | 14 + .../public/attack_discovery/types.ts | 23 - .../use_attack_discovery/helpers.ts | 16 +- .../use_attack_discovery/index.test.tsx | 222 ++++++++ .../use_attack_discovery/index.tsx | 341 ++++-------- .../public/common/lib/telemetry/constants.ts | 1 - .../events/attack_discovery/index.ts | 64 --- .../events/attack_discovery/types.ts | 26 - .../lib/telemetry/events/telemetry_events.ts | 2 - .../lib/telemetry/telemetry_client.mock.ts | 1 - .../common/lib/telemetry/telemetry_client.ts | 5 - .../public/common/lib/telemetry/types.ts | 11 - 94 files changed, 4812 insertions(+), 1458 deletions(-) create mode 100644 x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts create mode 100644 x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.schema.yaml create mode 100644 x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts create mode 100644 x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.schema.yaml create mode 100644 x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts create mode 100644 x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.schema.yaml create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/attack_discovery_schema.mock.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/create_attack_discovery.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/create_attack_discovery.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/field_maps_configuration.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/find_attack_discovery_by_connector_id.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/find_attack_discovery_by_connector_id.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/get_attack_discovery.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/get_attack_discovery.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/index.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/transforms.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/types.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/update_attack_discovery.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/update_attack_discovery.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts create mode 100644 x-pack/plugins/elastic_assistant/server/routes/attack_discovery/post_attack_discovery.test.ts delete mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/interval/helpers.ts delete mode 100644 x-pack/plugins/security_solution/public/attack_discovery/hooks/use_attack_discovery_telemetry/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/attack_discovery/hooks/use_attack_discovery_telemetry/index.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/hooks/use_poll_api.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/hooks/use_poll_api.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/failure/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/failure/index.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/failure/translations.ts delete mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.test.ts delete mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.ts delete mode 100644 x-pack/plugins/security_solution/public/attack_discovery/types.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/index.test.tsx delete mode 100644 x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/index.ts delete mode 100644 x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/types.ts diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts new file mode 100644 index 0000000000000..bc59404e0abff --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts @@ -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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Cancel Attack Discovery API endpoint + * version: 1 + */ + +import { z } from 'zod'; + +import { NonEmptyString } from '../common_attributes.gen'; +import { AttackDiscoveryResponse } from './common_attributes.gen'; + +export type AttackDiscoveryCancelRequestParams = z.infer; +export const AttackDiscoveryCancelRequestParams = z.object({ + /** + * The connector id for which to cancel a pending attack discovery + */ + connectorId: NonEmptyString, +}); +export type AttackDiscoveryCancelRequestParamsInput = z.input< + typeof AttackDiscoveryCancelRequestParams +>; + +export type AttackDiscoveryCancelResponse = z.infer; +export const AttackDiscoveryCancelResponse = AttackDiscoveryResponse; diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.schema.yaml new file mode 100644 index 0000000000000..553d741089cd0 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.schema.yaml @@ -0,0 +1,41 @@ +openapi: 3.0.0 +info: + title: Cancel Attack Discovery API endpoint + version: '1' +paths: + /internal/elastic_assistant/attack_discovery/cancel/{connectorId}: + put: + operationId: AttackDiscoveryCancel + x-codegen-enabled: true + description: Cancel relevant data for performing an attack discovery like pending requests + summary: Cancel relevant data for performing an attack discovery + tags: + - attack_discovery + parameters: + - name: 'connectorId' + in: path + required: true + description: The connector id for which to cancel a pending attack discovery + schema: + $ref: '../common_attributes.schema.yaml#/components/schemas/NonEmptyString' + responses: + '200': + description: Successful response + content: + application/json: + schema: + $ref: './common_attributes.schema.yaml#/components/schemas/AttackDiscoveryResponse' + + '400': + description: Generic Error + content: + application/json: + schema: + type: object + properties: + statusCode: + type: number + error: + type: string + message: + type: string diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts new file mode 100644 index 0000000000000..533acefe02156 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts @@ -0,0 +1,199 @@ +/* + * 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: Common Attack Discovery Attributes + * version: not applicable + */ + +import { z } from 'zod'; + +import { NonEmptyString, User } from '../common_attributes.gen'; +import { Replacements, ApiConfig } from '../conversations/common_attributes.gen'; + +/** + * An attack discovery generated from one or more alerts + */ +export type AttackDiscovery = z.infer; +export const AttackDiscovery = z.object({ + /** + * The alert IDs that the attack discovery is based on + */ + alertIds: z.array(z.string()), + /** + * UUID of attack discovery + */ + id: z.string().optional(), + /** + * Details of the attack with bulleted markdown that always uses special syntax for field names and values from the source data. + */ + detailsMarkdown: z.string(), + /** + * A short (no more than a sentence) summary of the attack discovery featuring only the host.name and user.name fields (when they are applicable), using the same syntax + */ + entitySummaryMarkdown: z.string(), + /** + * An array of MITRE ATT&CK tactic for the attack discovery + */ + mitreAttackTactics: z.array(z.string()).optional(), + /** + * A markdown summary of attack discovery, using the same syntax + */ + summaryMarkdown: z.string(), + /** + * A title for the attack discovery, in plain text + */ + title: z.string(), + /** + * The time the attack discovery was generated + */ + timestamp: NonEmptyString, +}); + +/** + * Array of attack discoveries + */ +export type AttackDiscoveries = z.infer; +export const AttackDiscoveries = z.array(AttackDiscovery); + +/** + * The status of the attack discovery. + */ +export type AttackDiscoveryStatus = z.infer; +export const AttackDiscoveryStatus = z.enum(['running', 'succeeded', 'failed', 'canceled']); +export type AttackDiscoveryStatusEnum = typeof AttackDiscoveryStatus.enum; +export const AttackDiscoveryStatusEnum = AttackDiscoveryStatus.enum; + +/** + * Run durations for the attack discovery + */ +export type GenerationInterval = z.infer; +export const GenerationInterval = z.object({ + /** + * The time the attack discovery was generated + */ + date: z.string(), + /** + * The duration of the attack discovery generation + */ + durationMs: z.number().int(), +}); + +export type AttackDiscoveryResponse = z.infer; +export const AttackDiscoveryResponse = z.object({ + id: NonEmptyString, + timestamp: NonEmptyString.optional(), + /** + * The last time attack discovery was updated. + */ + updatedAt: z.string().optional(), + /** + * The number of alerts in the context. + */ + alertsContextCount: z.number().int().optional(), + /** + * The time attack discovery was created. + */ + createdAt: z.string(), + replacements: Replacements.optional(), + users: z.array(User), + /** + * The status of the attack discovery. + */ + status: AttackDiscoveryStatus, + /** + * The attack discoveries. + */ + attackDiscoveries: AttackDiscoveries, + /** + * LLM API configuration. + */ + apiConfig: ApiConfig, + /** + * Kibana space + */ + namespace: z.string(), + /** + * The backing index required for update requests. + */ + backingIndex: z.string(), + /** + * The most 5 recent generation intervals + */ + generationIntervals: z.array(GenerationInterval), + /** + * The average generation interval in milliseconds + */ + averageIntervalMs: z.number().int(), + /** + * The reason for a status of failed. + */ + failureReason: z.string().optional(), +}); + +export type AttackDiscoveryUpdateProps = z.infer; +export const AttackDiscoveryUpdateProps = z.object({ + id: NonEmptyString, + /** + * LLM API configuration. + */ + apiConfig: ApiConfig.optional(), + /** + * The number of alerts in the context. + */ + alertsContextCount: z.number().int().optional(), + /** + * The attack discoveries. + */ + attackDiscoveries: AttackDiscoveries.optional(), + /** + * The status of the attack discovery. + */ + status: AttackDiscoveryStatus, + replacements: Replacements.optional(), + /** + * The most 5 recent generation intervals + */ + generationIntervals: z.array(GenerationInterval).optional(), + /** + * The backing index required for update requests. + */ + backingIndex: z.string(), + /** + * The reason for a status of failed. + */ + failureReason: z.string().optional(), +}); + +export type AttackDiscoveryCreateProps = z.infer; +export const AttackDiscoveryCreateProps = z.object({ + /** + * The attack discovery id. + */ + id: z.string().optional(), + /** + * The status of the attack discovery. + */ + status: AttackDiscoveryStatus, + /** + * The number of alerts in the context. + */ + alertsContextCount: z.number().int().optional(), + /** + * The attack discoveries. + */ + attackDiscoveries: AttackDiscoveries, + /** + * LLM API configuration. + */ + apiConfig: ApiConfig, + replacements: Replacements.optional(), +}); diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.schema.yaml new file mode 100644 index 0000000000000..634b5f0192a60 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.schema.yaml @@ -0,0 +1,197 @@ +openapi: 3.0.0 +info: + title: Common Attack Discovery Attributes + version: 'not applicable' +paths: {} +components: + x-codegen-enabled: true + schemas: + AttackDiscovery: + type: object + description: An attack discovery generated from one or more alerts + required: + - 'alertIds' + - 'detailsMarkdown' + - 'entitySummaryMarkdown' + - 'summaryMarkdown' + - 'timestamp' + - 'title' + properties: + alertIds: + description: The alert IDs that the attack discovery is based on + items: + type: string + type: array + id: + description: UUID of attack discovery + type: string + detailsMarkdown: + description: Details of the attack with bulleted markdown that always uses special syntax for field names and values from the source data. + type: string + entitySummaryMarkdown: + description: A short (no more than a sentence) summary of the attack discovery featuring only the host.name and user.name fields (when they are applicable), using the same syntax + type: string + mitreAttackTactics: + description: An array of MITRE ATT&CK tactic for the attack discovery + items: + type: string + type: array + summaryMarkdown: + description: A markdown summary of attack discovery, using the same syntax + type: string + title: + description: A title for the attack discovery, in plain text + type: string + timestamp: + description: The time the attack discovery was generated + $ref: '../common_attributes.schema.yaml#/components/schemas/NonEmptyString' + AttackDiscoveries: + type: array + description: Array of attack discoveries + items: + $ref: '#/components/schemas/AttackDiscovery' + + AttackDiscoveryStatus: + type: string + description: The status of the attack discovery. + enum: + - running + - succeeded + - failed + - canceled + + GenerationInterval: + type: object + description: Run durations for the attack discovery + required: + - 'date' + - 'durationMs' + properties: + date: + description: The time the attack discovery was generated + type: string + durationMs: + description: The duration of the attack discovery generation + type: integer + + + AttackDiscoveryResponse: + type: object + required: + - apiConfig + - id + - createdAt + - users + - namespace + - attackDiscoveries + - status + - backingIndex + - generationIntervals + - averageIntervalMs + properties: + id: + $ref: '../common_attributes.schema.yaml#/components/schemas/NonEmptyString' + 'timestamp': + $ref: '../common_attributes.schema.yaml#/components/schemas/NonEmptyString' + updatedAt: + description: The last time attack discovery was updated. + type: string + alertsContextCount: + type: integer + description: The number of alerts in the context. + createdAt: + description: The time attack discovery was created. + type: string + replacements: + $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/Replacements' + users: + type: array + items: + $ref: '../common_attributes.schema.yaml#/components/schemas/User' + status: + $ref: '#/components/schemas/AttackDiscoveryStatus' + description: The status of the attack discovery. + attackDiscoveries: + $ref: '#/components/schemas/AttackDiscoveries' + description: The attack discoveries. + apiConfig: + $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/ApiConfig' + description: LLM API configuration. + namespace: + type: string + description: Kibana space + backingIndex: + type: string + description: The backing index required for update requests. + generationIntervals: + type: array + description: The most 5 recent generation intervals + items: + $ref: '#/components/schemas/GenerationInterval' + averageIntervalMs: + type: integer + description: The average generation interval in milliseconds + failureReason: + type: string + description: The reason for a status of failed. + + AttackDiscoveryUpdateProps: + type: object + required: + - id + - status + - backingIndex + properties: + id: + $ref: '../common_attributes.schema.yaml#/components/schemas/NonEmptyString' + apiConfig: + $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/ApiConfig' + description: LLM API configuration. + alertsContextCount: + type: integer + description: The number of alerts in the context. + attackDiscoveries: + $ref: '#/components/schemas/AttackDiscoveries' + description: The attack discoveries. + status: + $ref: '#/components/schemas/AttackDiscoveryStatus' + description: The status of the attack discovery. + replacements: + $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/Replacements' + generationIntervals: + type: array + description: The most 5 recent generation intervals + items: + $ref: '#/components/schemas/GenerationInterval' + backingIndex: + type: string + description: The backing index required for update requests. + failureReason: + type: string + description: The reason for a status of failed. + + AttackDiscoveryCreateProps: + type: object + required: + - attackDiscoveries + - apiConfig + - status + properties: + id: + type: string + description: The attack discovery id. + status: + $ref: '#/components/schemas/AttackDiscoveryStatus' + description: The status of the attack discovery. + alertsContextCount: + type: integer + description: The number of alerts in the context. + attackDiscoveries: + $ref: '#/components/schemas/AttackDiscoveries' + description: The attack discoveries. + apiConfig: + $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/ApiConfig' + description: LLM API configuration. + replacements: + $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/Replacements' + diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts new file mode 100644 index 0000000000000..3e58606df8298 --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts @@ -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. + */ + +/* + * NOTICE: Do not edit this file manually. + * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. + * + * info: + * title: Get Attack Discovery API endpoint + * version: 1 + */ + +import { z } from 'zod'; + +import { NonEmptyString } from '../common_attributes.gen'; +import { AttackDiscoveryResponse } from './common_attributes.gen'; + +export type AttackDiscoveryGetRequestParams = z.infer; +export const AttackDiscoveryGetRequestParams = z.object({ + /** + * The connector id for which to get the attack discovery + */ + connectorId: NonEmptyString, +}); +export type AttackDiscoveryGetRequestParamsInput = z.input; + +export type AttackDiscoveryGetResponse = z.infer; +export const AttackDiscoveryGetResponse = z.object({ + data: AttackDiscoveryResponse.optional(), + /** + * Indicates if an attack discovery exists for the given connectorId + */ + entryExists: z.boolean(), +}); diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.schema.yaml new file mode 100644 index 0000000000000..4c1f11462744e --- /dev/null +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.schema.yaml @@ -0,0 +1,48 @@ +openapi: 3.0.0 +info: + title: Get Attack Discovery API endpoint + version: '1' +paths: + /internal/elastic_assistant/attack_discovery/{connectorId}: + get: + operationId: AttackDiscoveryGet + x-codegen-enabled: true + description: Get relevant data for performing an attack discovery like pending requests + summary: Get relevant data for performing an attack discovery + tags: + - attack_discovery + parameters: + - name: 'connectorId' + in: path + required: true + description: The connector id for which to get the attack discovery + schema: + $ref: '../common_attributes.schema.yaml#/components/schemas/NonEmptyString' + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: object + properties: + data: + $ref: './common_attributes.schema.yaml#/components/schemas/AttackDiscoveryResponse' + entryExists: + type: boolean + description: Indicates if an attack discovery exists for the given connectorId + required: + - entryExists + '400': + description: Generic Error + content: + application/json: + schema: + type: object + properties: + statusCode: + type: number + error: + type: string + message: + type: string diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts index cfc7d5285ddac..d2912c6e09ba2 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts @@ -10,52 +10,24 @@ * This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator. * * info: - * title: Attack discovery API endpoint + * title: Post Attack discovery API endpoint * version: 1 */ import { z } from 'zod'; import { AnonymizationFieldResponse } from '../anonymization_fields/bulk_crud_anonymization_fields_route.gen'; -import { Replacements, TraceData } from '../conversations/common_attributes.gen'; - -/** - * An attack discovery generated from one or more alerts - */ -export type AttackDiscovery = z.infer; -export const AttackDiscovery = z.object({ - /** - * The alert IDs that the attack discovery is based on - */ - alertIds: z.array(z.string()), - /** - * Details of the attack with bulleted markdown that always uses special syntax for field names and values from the source data. - */ - detailsMarkdown: z.string(), - /** - * A short (no more than a sentence) summary of the attack discovery featuring only the host.name and user.name fields (when they are applicable), using the same syntax - */ - entitySummaryMarkdown: z.string(), - /** - * An array of MITRE ATT&CK tactic for the attack discovery - */ - mitreAttackTactics: z.array(z.string()).optional(), - /** - * A markdown summary of attack discovery, using the same syntax - */ - summaryMarkdown: z.string(), - /** - * A title for the attack discovery, in plain text - */ - title: z.string(), -}); +import { ApiConfig, Replacements } from '../conversations/common_attributes.gen'; +import { AttackDiscoveryResponse } from './common_attributes.gen'; export type AttackDiscoveryPostRequestBody = z.infer; export const AttackDiscoveryPostRequestBody = z.object({ alertsIndexPattern: z.string(), anonymizationFields: z.array(AnonymizationFieldResponse), - connectorId: z.string(), - actionTypeId: z.string(), + /** + * LLM API configuration. + */ + apiConfig: ApiConfig, langSmithProject: z.string().optional(), langSmithApiKey: z.string().optional(), model: z.string().optional(), @@ -66,11 +38,4 @@ export const AttackDiscoveryPostRequestBody = z.object({ export type AttackDiscoveryPostRequestBodyInput = z.input; export type AttackDiscoveryPostResponse = z.infer; -export const AttackDiscoveryPostResponse = z.object({ - connector_id: z.string().optional(), - alertsContextCount: z.number().optional(), - attackDiscoveries: z.array(AttackDiscovery).optional(), - replacements: Replacements.optional(), - status: z.string().optional(), - trace_data: TraceData.optional(), -}); +export const AttackDiscoveryPostResponse = AttackDiscoveryResponse; diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.schema.yaml index 44acb268700a5..1c658174abd5c 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.schema.yaml +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.schema.yaml @@ -1,43 +1,9 @@ openapi: 3.0.0 info: - title: Attack discovery API endpoint + title: Post Attack discovery API endpoint version: '1' components: x-codegen-enabled: true - schemas: - AttackDiscovery: - type: object - description: An attack discovery generated from one or more alerts - required: - - 'alertIds' - - 'detailsMarkdown' - - 'entitySummaryMarkdown' - - 'summaryMarkdown' - - 'title' - properties: - alertIds: - description: The alert IDs that the attack discovery is based on - items: - type: string - type: array - detailsMarkdown: - description: Details of the attack with bulleted markdown that always uses special syntax for field names and values from the source data. - type: string - entitySummaryMarkdown: - description: A short (no more than a sentence) summary of the attack discovery featuring only the host.name and user.name fields (when they are applicable), using the same syntax - type: string - mitreAttackTactics: - description: An array of MITRE ATT&CK tactic for the attack discovery - items: - type: string - type: array - summaryMarkdown: - description: A markdown summary of attack discovery, using the same syntax - type: string - title: - description: A title for the attack discovery, in plain text - type: string - paths: /internal/elastic_assistant/attack_discovery: @@ -56,10 +22,9 @@ paths: schema: type: object required: - - actionTypeId + - apiConfig - alertsIndexPattern - anonymizationFields - - connectorId - size - subAction properties: @@ -69,10 +34,9 @@ paths: items: $ref: '../anonymization_fields/bulk_crud_anonymization_fields_route.schema.yaml#/components/schemas/AnonymizationFieldResponse' type: array - connectorId: - type: string - actionTypeId: - type: string + apiConfig: + $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/ApiConfig' + description: LLM API configuration. langSmithProject: type: string langSmithApiKey: @@ -94,22 +58,7 @@ paths: content: application/json: schema: - type: object - properties: - connector_id: - type: string - alertsContextCount: - type: number - attackDiscoveries: - type: array - items: - $ref: '#/components/schemas/AttackDiscovery' - replacements: - $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/Replacements' - status: - type: string - trace_data: - $ref: '../conversations/common_attributes.schema.yaml#/components/schemas/TraceData' + $ref: './common_attributes.schema.yaml#/components/schemas/AttackDiscoveryResponse' '400': description: Bad request content: diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts index bbed67f4814fc..03f63ec0f2d29 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.gen.ts @@ -108,11 +108,11 @@ export const Message = z.object({ export type ApiConfig = z.infer; export const ApiConfig = z.object({ /** - * connector Id + * connector id */ connectorId: z.string(), /** - * action type Id + * action type id */ actionTypeId: z.string(), /** diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.schema.yaml b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.schema.yaml index 49aaaa5663a1c..f6a8189182474 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.schema.yaml +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/conversations/common_attributes.schema.yaml @@ -93,10 +93,10 @@ components: properties: connectorId: type: string - description: connector Id + description: connector id actionTypeId: type: string - description: action type Id + description: action type id defaultSystemPromptId: type: string description: defaultSystemPromptId diff --git a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts index ae66432af3076..8f47731694cf3 100644 --- a/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts +++ b/x-pack/packages/kbn-elastic-assistant-common/impl/schemas/index.ts @@ -22,7 +22,10 @@ export const INTERNAL_API_ACCESS = 'internal'; export * from './common_attributes.gen'; // Attack discovery Schemas +export * from './attack_discovery/common_attributes.gen'; +export * from './attack_discovery/get_attack_discovery_route.gen'; export * from './attack_discovery/post_attack_discovery_route.gen'; +export * from './attack_discovery/cancel_attack_discovery_route.gen'; // Evaluation Schemas export * from './evaluation/post_evaluate_route.gen'; diff --git a/x-pack/plugins/elastic_assistant/common/constants.ts b/x-pack/plugins/elastic_assistant/common/constants.ts index d8c2630c1aef8..45b473e848750 100755 --- a/x-pack/plugins/elastic_assistant/common/constants.ts +++ b/x-pack/plugins/elastic_assistant/common/constants.ts @@ -14,6 +14,8 @@ export const POST_ACTIONS_CONNECTOR_EXECUTE = `${BASE_PATH}/actions/connector/{c // Attack discovery export const ATTACK_DISCOVERY = `${BASE_PATH}/attack_discovery`; +export const ATTACK_DISCOVERY_BY_CONNECTOR_ID = `${ATTACK_DISCOVERY}/{connectorId}`; +export const ATTACK_DISCOVERY_CANCEL_BY_CONNECTOR_ID = `${ATTACK_DISCOVERY}/cancel/{connectorId}`; // Model Evaluation export const EVALUATE = `${BASE_PATH}/evaluate`; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/attack_discovery_schema.mock.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/attack_discovery_schema.mock.ts new file mode 100644 index 0000000000000..156011cfbae14 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/attack_discovery_schema.mock.ts @@ -0,0 +1,128 @@ +/* + * 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 { estypes } from '@elastic/elasticsearch'; +import { EsAttackDiscoverySchema } from '../ai_assistant_data_clients/attack_discovery/types'; + +export const getAttackDiscoverySearchEsMock = () => { + const searchResponse: estypes.SearchResponse = { + took: 3, + timed_out: false, + _shards: { + total: 2, + successful: 2, + skipped: 0, + failed: 0, + }, + hits: { + total: { + value: 1, + relation: 'eq', + }, + max_score: 0, + hits: [ + { + _index: 'foo', + _id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + _source: { + id: '04128c15-0d1b-4716-a4c5-46997ac7f3bd', + '@timestamp': '2024-06-07T18:56:17.357Z', + created_at: '2024-06-07T18:56:17.357Z', + users: [ + { + id: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + name: 'elastic', + }, + ], + status: 'succeeded', + api_config: { + action_type_id: '.gen-ai', + connector_id: 'my-gpt4o-ai', + }, + attack_discoveries: [ + { + summary_markdown: + 'Critical malware detected on {{ host.name cd854ec0-1096-4ca6-a7b8-582655d6b970 }} involving {{ user.name f19e1a0a-de3b-496c-8ace-dd91229e1084 }}. The malware, identified as {{ file.name My Go Application.app }}, was executed with the command line {{ process.command_line xpcproxy application.Appify by Machine Box.My Go Application.20.23 }}.', + id: 'a45bc1af-e652-4f3b-b8ce-408028f29824', + title: 'Critical Malware Detection', + mitre_attack_tactics: ['Execution', 'Persistence', 'Privilege Escalation'], + alert_ids: [ + '094e59adc680420aeb1e0f872b52e17bd2f61aaddde521d53600f0576062ac4d', + 'fdcb45018d3aac5e7a529a455aedc9276ef89b386ca4dbae1d721dd383577d21', + '82baa43f7514ee7fb107ae032606d33afc6092a9c9a9caeffd1fe120a7640698', + 'aef4302768e19c5413c53203c14624bdf9d0656fa3d1d439c633c9880a2f3f6e', + '04cbafe6d7f965908a9155ae0bc559ce537faaf06266df732d7bd6897c83e77e', + '6f73d978ea02a471eba8d82772dc16f26622628b93fa0a651ce847fe7baf9e64', + '7ff1cd151bfdd2678d9efd4e22bfaf15dbfd89a81f40ea2160769c143ecca082', + 'dee8604204be00bc61112fe81358089a5e4d494ac28c95937758383f391a8cec', + '4c49b1fbcb6f9a4cfb355f56edfbc0d5320cd65f9f720546dd99e51d8d6eef84', + ], + details_markdown: `"""- **Host**: {{ host.name cd854ec0-1096-4ca6-a7b8-582655d6b970 }}\n- **User**: {{ user.name f19e1a0a-de3b-496c-8ace-dd91229e1084 }}\n- **Malware**: {{ file.name My Go Application.app }}\n- **Path**: {{ file.path /private/var/folders/_b/rmcpc65j6nv11ygrs50ctcjr0000gn/T/AppTranslocation/37D933EC-334D-410A-A741-0F730D6AE3FD/d/Setup.app/Contents/MacOS/My Go Application.app }}\n- **Command Line**: {{ process.command_line xpcproxy application.Appify by Machine Box.My Go Application.20.23 }}\n- **SHA256**: {{ process.hash.sha256 2c63ba2b1a5131b80e567b7a1a93997a2de07ea20d0a8f5149701c67b832c097 }}\n- **Parent Process**: {{ process.parent.name launchd }}\n- **Parent Command Line**: {{ process.parent.command_line /sbin/launchd }}\n- **Code Signature**: {{ process.code_signature.status code failed to satisfy specified code requirement(s) }}"""`, + entity_summary_markdown: + '{{ host.name cd854ec0-1096-4ca6-a7b8-582655d6b970 }} and {{ user.name f19e1a0a-de3b-496c-8ace-dd91229e1084 }} involved in critical malware detection.', + timestamp: '2024-06-07T21:19:08.090Z', + }, + ], + updated_at: '2024-06-07T21:19:08.090Z', + replacements: [ + { + uuid: 'f19e1a0a-de3b-496c-8ace-dd91229e1084', + value: 'root', + }, + { + uuid: 'cd854ec0-1096-4ca6-a7b8-582655d6b970', + value: 'SRVMAC08', + }, + { + uuid: '3517f073-7f5e-42b4-9c42-e8a25dc9e27e', + value: 'james', + }, + { + uuid: 'f04af949-504e-4374-a31e-447e7d5b252e', + value: 'Administrator', + }, + { + uuid: '7eecfdbb-373a-4cbb-9bf7-e91a0be73b29', + value: 'SRVWIN07-PRIV', + }, + { + uuid: '8b73ea51-4c7a-4caa-a424-5b2495eabd2a', + value: 'SRVWIN07', + }, + { + uuid: '908405b1-fc8b-4fef-9bdf-35895896a1e3', + value: 'SRVWIN06', + }, + { + uuid: '7e8a2687-74d6-47d2-951c-522e21a44853', + value: 'SRVNIX05', + }, + ], + namespace: 'default', + generation_intervals: [ + { + date: '2024-06-07T21:19:08.089Z', + duration_ms: 110906, + }, + { + date: '2024-06-07T20:04:35.715Z', + duration_ms: 104593, + }, + { + date: '2024-06-07T18:58:27.880Z', + duration_ms: 130526, + }, + ], + alerts_context_count: 20, + average_interval_ms: 115341, + }, + }, + ], + }, + }; + return searchResponse; +}; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/data_clients.mock.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/data_clients.mock.ts index be69365724341..a5196f93b6917 100644 --- a/x-pack/plugins/elastic_assistant/server/__mocks__/data_clients.mock.ts +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/data_clients.mock.ts @@ -8,9 +8,12 @@ import type { PublicMethodsOf } from '@kbn/utility-types'; import { AIAssistantConversationsDataClient } from '../ai_assistant_data_clients/conversations'; import { AIAssistantDataClient } from '../ai_assistant_data_clients'; +import { AttackDiscoveryDataClient } from '../ai_assistant_data_clients/attack_discovery'; type ConversationsDataClientContract = PublicMethodsOf; export type ConversationsDataClientMock = jest.Mocked; +type AttackDiscoveryDataClientContract = PublicMethodsOf; +export type AttackDiscoveryDataClientMock = jest.Mocked; const createConversationsDataClientMock = () => { const mocked: ConversationsDataClientMock = { @@ -32,6 +35,22 @@ export const conversationsDataClientMock: { create: createConversationsDataClientMock, }; +const createAttackDiscoveryDataClientMock = (): AttackDiscoveryDataClientMock => ({ + getAttackDiscovery: jest.fn(), + createAttackDiscovery: jest.fn(), + findAttackDiscoveryByConnectorId: jest.fn(), + updateAttackDiscovery: jest.fn(), + getReader: jest.fn(), + getWriter: jest.fn().mockResolvedValue({ bulk: jest.fn() }), + findDocuments: jest.fn(), +}); + +export const attackDiscoveryDataClientMock: { + create: () => AttackDiscoveryDataClientMock; +} = { + create: createAttackDiscoveryDataClientMock, +}; + type AIAssistantDataClientContract = PublicMethodsOf; export type AIAssistantDataClientMock = jest.Mocked; diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts index 0850938633322..2407e09df1e55 100644 --- a/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/request.ts @@ -5,8 +5,15 @@ * 2.0. */ import { httpServerMock } from '@kbn/core/server/mocks'; -import { CAPABILITIES, EVALUATE } from '../../common/constants'; import { + ATTACK_DISCOVERY, + ATTACK_DISCOVERY_BY_CONNECTOR_ID, + ATTACK_DISCOVERY_CANCEL_BY_CONNECTOR_ID, + CAPABILITIES, + EVALUATE, +} from '../../common/constants'; +import { + AttackDiscoveryPostRequestBody, ConversationCreateProps, ConversationUpdateProps, ELASTIC_AI_ASSISTANT_ANONYMIZATION_FIELDS_URL_BULK_ACTION, @@ -188,3 +195,24 @@ export const getAnonymizationFieldsBulkActionRequest = ( }, }, }); + +export const getCancelAttackDiscoveryRequest = (connectorId: string) => + requestMock.create({ + method: 'put', + path: ATTACK_DISCOVERY_CANCEL_BY_CONNECTOR_ID, + params: { connectorId }, + }); + +export const getAttackDiscoveryRequest = (connectorId: string) => + requestMock.create({ + method: 'get', + path: ATTACK_DISCOVERY_BY_CONNECTOR_ID, + params: { connectorId }, + }); + +export const postAttackDiscoveryRequest = (body: AttackDiscoveryPostRequestBody) => + requestMock.create({ + method: 'post', + path: ATTACK_DISCOVERY, + body, + }); diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts index 6c5d9b2bc4d57..c6a9951e89e3e 100644 --- a/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/request_context.ts @@ -14,11 +14,16 @@ import { ElasticAssistantRequestHandlerContext, } from '../types'; import { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; -import { conversationsDataClientMock, dataClientMock } from './data_clients.mock'; +import { + attackDiscoveryDataClientMock, + conversationsDataClientMock, + dataClientMock, +} from './data_clients.mock'; import { AIAssistantConversationsDataClient } from '../ai_assistant_data_clients/conversations'; import { AIAssistantDataClient } from '../ai_assistant_data_clients'; import { AIAssistantKnowledgeBaseDataClient } from '../ai_assistant_data_clients/knowledge_base'; import { defaultAssistantFeatures } from '@kbn/elastic-assistant-common'; +import { AttackDiscoveryDataClient } from '../ai_assistant_data_clients/attack_discovery'; export const createMockClients = () => { const core = coreMock.createRequestHandlerContext(); @@ -36,6 +41,7 @@ export const createMockClients = () => { getAIAssistantConversationsDataClient: conversationsDataClientMock.create(), getAIAssistantKnowledgeBaseDataClient: dataClientMock.create(), getAIAssistantPromptsDataClient: dataClientMock.create(), + getAttackDiscoveryDataClient: attackDiscoveryDataClientMock.create(), getAIAssistantAnonymizationFieldsDataClient: dataClientMock.create(), getSpaceId: jest.fn(), getCurrentUser: jest.fn(), @@ -109,6 +115,10 @@ const createElasticAssistantRequestContextMock = ( () => clients.elasticAssistant.getAIAssistantPromptsDataClient ) as unknown as jest.MockInstance, [], unknown> & (() => Promise), + getAttackDiscoveryDataClient: jest.fn( + () => clients.elasticAssistant.getAttackDiscoveryDataClient + ) as unknown as jest.MockInstance, [], unknown> & + (() => Promise), getAIAssistantKnowledgeBaseDataClient: jest.fn( () => clients.elasticAssistant.getAIAssistantKnowledgeBaseDataClient ) as unknown as jest.MockInstance< diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts index dc5a2ba0e884a..def0a81acea37 100644 --- a/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/response.ts @@ -15,6 +15,8 @@ import { EsPromptsSchema } from '../ai_assistant_data_clients/prompts/types'; import { getPromptsSearchEsMock } from './prompts_schema.mock'; import { EsAnonymizationFieldsSchema } from '../ai_assistant_data_clients/anonymization_fields/types'; import { getAnonymizationFieldsSearchEsMock } from './anonymization_fields_schema.mock'; +import { getAttackDiscoverySearchEsMock } from './attack_discovery_schema.mock'; +import { EsAttackDiscoverySchema } from '../ai_assistant_data_clients/attack_discovery/types'; export const responseMock = { create: httpServerMock.createResponseFactory, @@ -34,6 +36,14 @@ export const getFindConversationsResultWithSingleHit = (): FindResponse => ({ + page: 1, + perPage: 1, + total: 1, + data: getAttackDiscoverySearchEsMock(), + }); + export const getFindPromptsResultWithSingleHit = (): FindResponse => ({ page: 1, perPage: 1, diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/create_attack_discovery.test.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/create_attack_discovery.test.ts new file mode 100644 index 0000000000000..e8ccdbc1d25ca --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/create_attack_discovery.test.ts @@ -0,0 +1,77 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; + +import { createAttackDiscovery } from './create_attack_discovery'; +import { AttackDiscoveryCreateProps, AttackDiscoveryResponse } from '@kbn/elastic-assistant-common'; +import { AuthenticatedUser } from '@kbn/security-plugin-types-common'; +import { getAttackDiscovery } from './get_attack_discovery'; +import { loggerMock } from '@kbn/logging-mocks'; +const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); +const mockLogger = loggerMock.create(); +jest.mock('./get_attack_discovery'); +const attackDiscoveryCreate: AttackDiscoveryCreateProps = { + attackDiscoveries: [], + apiConfig: { + actionTypeId: 'action-type-id', + connectorId: 'connector-id', + defaultSystemPromptId: 'default-prompt-id', + model: 'model-name', + provider: 'OpenAI', + }, + alertsContextCount: 10, + replacements: { key1: 'value1', key2: 'value2' }, + status: 'running', +}; + +const user = { + username: 'test_user', + profile_uid: '1234', + authentication_realm: { + type: 'my_realm_type', + name: 'my_realm_name', + }, +} as AuthenticatedUser; + +const mockArgs = { + esClient: mockEsClient, + attackDiscoveryIndex: 'attack-discovery-index', + spaceId: 'space-1', + user, + attackDiscoveryCreate, + logger: mockLogger, +}; +const mockGetAttackDiscovery = jest.mocked(getAttackDiscovery); + +describe('createAttackDiscovery', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should create attack discovery successfully', async () => { + // @ts-expect-error not full response interface + mockEsClient.create.mockResolvedValueOnce({ _id: 'created_id' }); + mockGetAttackDiscovery.mockResolvedValueOnce({ + id: 'created_id', + // ... other attack discovery properties + } as AttackDiscoveryResponse); + + const response = await createAttackDiscovery(mockArgs); + expect(response).not.toBeNull(); + expect(response!.id).toEqual('created_id'); + expect(mockEsClient.create).toHaveBeenCalledTimes(1); + expect(mockGetAttackDiscovery).toHaveBeenCalledTimes(1); + }); + + it('should throw error on elasticsearch create failure', async () => { + mockEsClient.create.mockRejectedValueOnce(new Error('Elasticsearch error')); + await expect(createAttackDiscovery(mockArgs)).rejects.toThrowError('Elasticsearch error'); + expect(mockEsClient.create).toHaveBeenCalledTimes(1); + expect(mockGetAttackDiscovery).not.toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/create_attack_discovery.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/create_attack_discovery.ts new file mode 100644 index 0000000000000..937c78e4b9eb1 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/create_attack_discovery.ts @@ -0,0 +1,107 @@ +/* + * 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 { v4 as uuidv4 } from 'uuid'; +import { ElasticsearchClient, Logger } from '@kbn/core/server'; + +import { AttackDiscoveryCreateProps, AttackDiscoveryResponse } from '@kbn/elastic-assistant-common'; +import { AuthenticatedUser } from '@kbn/security-plugin-types-common'; +import { getAttackDiscovery } from './get_attack_discovery'; +import { CreateAttackDiscoverySchema } from './types'; + +export interface CreateAttackDiscoveryParams { + esClient: ElasticsearchClient; + logger: Logger; + attackDiscoveryIndex: string; + spaceId: string; + user: AuthenticatedUser; + attackDiscoveryCreate: AttackDiscoveryCreateProps; +} + +export const createAttackDiscovery = async ({ + esClient, + attackDiscoveryIndex, + spaceId, + user, + attackDiscoveryCreate, + logger, +}: CreateAttackDiscoveryParams): Promise => { + const createdAt = new Date().toISOString(); + const body = transformToCreateScheme(createdAt, spaceId, user, attackDiscoveryCreate); + const id = attackDiscoveryCreate?.id || uuidv4(); + try { + const response = await esClient.create({ + body, + id, + index: attackDiscoveryIndex, + refresh: 'wait_for', + }); + + const createdAttackDiscovery = await getAttackDiscovery({ + esClient, + attackDiscoveryIndex, + id: response._id, + logger, + user, + }); + return createdAttackDiscovery; + } catch (err) { + logger.error(`Error creating attack discovery: ${err} with id: ${id}`); + throw err; + } +}; + +export const transformToCreateScheme = ( + createdAt: string, + spaceId: string, + user: AuthenticatedUser, + { + attackDiscoveries, + apiConfig, + alertsContextCount, + replacements, + status, + }: AttackDiscoveryCreateProps +): CreateAttackDiscoverySchema => { + return { + '@timestamp': createdAt, + created_at: createdAt, + users: [ + { + id: user.profile_uid, + name: user.username, + }, + ], + status, + api_config: { + action_type_id: apiConfig.actionTypeId, + connector_id: apiConfig.connectorId, + default_system_prompt_id: apiConfig.defaultSystemPromptId, + model: apiConfig.model, + provider: apiConfig.provider, + }, + alerts_context_count: alertsContextCount, + attack_discoveries: attackDiscoveries?.map((attackDiscovery) => ({ + id: attackDiscovery.id, + alert_ids: attackDiscovery.alertIds, + title: attackDiscovery.title, + details_markdown: attackDiscovery.detailsMarkdown, + entity_summary_markdown: attackDiscovery.entitySummaryMarkdown, + mitre_attack_tactics: attackDiscovery.mitreAttackTactics, + summary_markdown: attackDiscovery.summaryMarkdown, + timestamp: attackDiscovery.timestamp ?? createdAt, + })), + updated_at: createdAt, + replacements: replacements + ? Object.keys(replacements).map((key) => ({ + uuid: key, + value: replacements[key], + })) + : undefined, + namespace: spaceId, + }; +}; diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/field_maps_configuration.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/field_maps_configuration.ts new file mode 100644 index 0000000000000..51773489c4d6b --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/field_maps_configuration.ts @@ -0,0 +1,181 @@ +/* + * 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 { FieldMap } from '@kbn/data-stream-adapter'; + +export const attackDiscoveryFieldMap: FieldMap = { + '@timestamp': { + type: 'date', + array: false, + required: false, + }, + users: { + type: 'nested', + array: true, + required: false, + }, + 'users.id': { + type: 'keyword', + array: false, + required: true, + }, + 'users.name': { + type: 'keyword', + array: false, + required: false, + }, + id: { + type: 'keyword', + array: false, + required: true, + }, + updated_at: { + type: 'date', + array: false, + required: false, + }, + created_at: { + type: 'date', + array: false, + required: false, + }, + attack_discoveries: { + type: 'nested', + array: true, + required: false, + }, + 'attack_discoveries.timestamp': { + type: 'date', + array: false, + required: true, + }, + 'attack_discoveries.details_markdown': { + type: 'text', + array: false, + required: true, + }, + + 'attack_discoveries.title': { + type: 'text', + array: false, + required: true, + }, + + 'attack_discoveries.entity_summary_markdown': { + type: 'text', + array: false, + required: true, + }, + + 'attack_discoveries.summary_markdown': { + type: 'text', + array: false, + required: true, + }, + + 'attack_discoveries.mitre_attack_tactics': { + type: 'keyword', + array: true, + required: false, + }, + + 'attack_discoveries.id': { + type: 'keyword', + required: false, + }, + + 'attack_discoveries.alert_ids': { + type: 'keyword', + array: true, + required: true, + }, + + replacements: { + type: 'object', + array: false, + required: false, + }, + 'replacements.value': { + type: 'keyword', + array: false, + required: false, + }, + 'replacements.uuid': { + type: 'keyword', + array: false, + required: false, + }, + api_config: { + type: 'object', + array: false, + required: true, + }, + 'api_config.connector_id': { + type: 'keyword', + array: false, + required: true, + }, + 'api_config.action_type_id': { + type: 'keyword', + array: false, + required: false, + }, + 'api_config.default_system_prompt_id': { + type: 'keyword', + array: false, + required: false, + }, + 'api_config.provider': { + type: 'keyword', + array: false, + required: false, + }, + 'api_config.model': { + type: 'keyword', + array: false, + required: false, + }, + alerts_context_count: { + type: 'integer', + array: false, + required: false, + }, + status: { + type: 'keyword', + array: false, + required: true, + }, + namespace: { + type: 'keyword', + array: false, + required: true, + }, + average_interval_ms: { + type: 'integer', + array: false, + required: false, + }, + failure_reason: { + type: 'keyword', + array: false, + required: false, + }, + generation_intervals: { + type: 'nested', + array: true, + required: false, + }, + 'generation_intervals.date': { + type: 'date', + array: false, + required: true, + }, + 'generation_intervals.duration_ms': { + type: 'integer', + array: false, + required: true, + }, +} as const; diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/find_attack_discovery_by_connector_id.test.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/find_attack_discovery_by_connector_id.test.ts new file mode 100644 index 0000000000000..10688ce25b25e --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/find_attack_discovery_by_connector_id.test.ts @@ -0,0 +1,69 @@ +/* + * 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 { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { loggerMock } from '@kbn/logging-mocks'; +import { findAttackDiscoveryByConnectorId } from './find_attack_discovery_by_connector_id'; +import { AuthenticatedUser } from '@kbn/core-security-common'; +import { getAttackDiscoverySearchEsMock } from '../../__mocks__/attack_discovery_schema.mock'; + +const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); +const mockLogger = loggerMock.create(); + +const mockResponse = getAttackDiscoverySearchEsMock(); + +const user = { + username: 'test_user', + profile_uid: '1234', + authentication_realm: { + type: 'my_realm_type', + name: 'my_realm_name', + }, +} as AuthenticatedUser; +const mockRequest = { + esClient: mockEsClient, + attackDiscoveryIndex: 'attack-discovery-index', + connectorId: 'connector-id', + user, + logger: mockLogger, +}; +describe('findAttackDiscoveryByConnectorId', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should find attack discovery by connector id successfully', async () => { + mockEsClient.search.mockResolvedValueOnce(mockResponse); + + const response = await findAttackDiscoveryByConnectorId(mockRequest); + + expect(response).not.toBeNull(); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockLogger.error).not.toHaveBeenCalled(); + }); + + it('should return null if no attack discovery found', async () => { + mockEsClient.search.mockResolvedValueOnce({ ...mockResponse, hits: { hits: [] } }); + + const response = await findAttackDiscoveryByConnectorId(mockRequest); + + expect(response).toBeNull(); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockLogger.error).not.toHaveBeenCalled(); + }); + + it('should throw error on elasticsearch search failure', async () => { + mockEsClient.search.mockRejectedValueOnce(new Error('Elasticsearch error')); + + await expect(findAttackDiscoveryByConnectorId(mockRequest)).rejects.toThrowError( + 'Elasticsearch error' + ); + + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockLogger.error).toHaveBeenCalledTimes(1); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/find_attack_discovery_by_connector_id.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/find_attack_discovery_by_connector_id.ts new file mode 100644 index 0000000000000..28a99cb644951 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/find_attack_discovery_by_connector_id.ts @@ -0,0 +1,78 @@ +/* + * 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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { AttackDiscoveryResponse } from '@kbn/elastic-assistant-common'; +import { AuthenticatedUser } from '@kbn/security-plugin/common'; +import { EsAttackDiscoverySchema } from './types'; +import { transformESSearchToAttackDiscovery } from './transforms'; + +export interface FindAttackDiscoveryParams { + esClient: ElasticsearchClient; + logger: Logger; + attackDiscoveryIndex: string; + connectorId: string; + user: AuthenticatedUser; +} + +export const findAttackDiscoveryByConnectorId = async ({ + esClient, + logger, + attackDiscoveryIndex, + connectorId, + user, +}: FindAttackDiscoveryParams): Promise => { + const filterByUser = [ + { + nested: { + path: 'users', + query: { + bool: { + must: [ + { + match: user.profile_uid + ? { 'users.id': user.profile_uid } + : { 'users.name': user.username }, + }, + ], + }, + }, + }, + }, + ]; + try { + const response = await esClient.search({ + query: { + bool: { + must: [ + { + bool: { + should: [ + { + term: { + 'api_config.connector_id': connectorId, + }, + }, + ], + }, + }, + ...filterByUser, + ], + }, + }, + _source: true, + ignore_unavailable: true, + index: attackDiscoveryIndex, + seq_no_primary_term: true, + }); + const attackDiscovery = transformESSearchToAttackDiscovery(response); + return attackDiscovery[0] ?? null; + } catch (err) { + logger.error(`Error fetching attack discovery: ${err} with connectorId: ${connectorId}`); + throw err; + } +}; diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/get_attack_discovery.test.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/get_attack_discovery.test.ts new file mode 100644 index 0000000000000..4ee89fb7a3bc0 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/get_attack_discovery.test.ts @@ -0,0 +1,67 @@ +/* + * 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 { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { loggerMock } from '@kbn/logging-mocks'; +import { getAttackDiscovery } from './get_attack_discovery'; +import { getAttackDiscoverySearchEsMock } from '../../__mocks__/attack_discovery_schema.mock'; +import { AuthenticatedUser } from '@kbn/core-security-common'; + +const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); +const mockLogger = loggerMock.create(); + +const mockResponse = getAttackDiscoverySearchEsMock(); + +const user = { + username: 'test_user', + profile_uid: '1234', + authentication_realm: { + type: 'my_realm_type', + name: 'my_realm_name', + }, +} as AuthenticatedUser; +const mockRequest = { + esClient: mockEsClient, + attackDiscoveryIndex: 'attack-discovery-index', + id: 'discovery-id', + user, + logger: mockLogger, +}; +describe('getAttackDiscovery', () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should get attack discovery by id successfully', async () => { + mockEsClient.search.mockResolvedValueOnce(mockResponse); + + const response = await getAttackDiscovery(mockRequest); + + expect(response).not.toBeNull(); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockLogger.error).not.toHaveBeenCalled(); + }); + + it('should return null if no attack discovery found', async () => { + mockEsClient.search.mockResolvedValueOnce({ ...mockResponse, hits: { hits: [] } }); + + const response = await getAttackDiscovery(mockRequest); + + expect(response).toBeNull(); + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockLogger.error).not.toHaveBeenCalled(); + }); + + it('should throw error on elasticsearch search failure', async () => { + mockEsClient.search.mockRejectedValueOnce(new Error('Elasticsearch error')); + + await expect(getAttackDiscovery(mockRequest)).rejects.toThrowError('Elasticsearch error'); + + expect(mockEsClient.search).toHaveBeenCalledTimes(1); + expect(mockLogger.error).toHaveBeenCalledTimes(1); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/get_attack_discovery.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/get_attack_discovery.ts new file mode 100644 index 0000000000000..57d4e167d2fa9 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/get_attack_discovery.ts @@ -0,0 +1,78 @@ +/* + * 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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { AttackDiscoveryResponse } from '@kbn/elastic-assistant-common'; +import { AuthenticatedUser } from '@kbn/security-plugin/common'; +import { EsAttackDiscoverySchema } from './types'; +import { transformESSearchToAttackDiscovery } from './transforms'; + +export interface GetAttackDiscoveryParams { + esClient: ElasticsearchClient; + logger: Logger; + attackDiscoveryIndex: string; + id: string; + user: AuthenticatedUser; +} + +export const getAttackDiscovery = async ({ + esClient, + logger, + attackDiscoveryIndex, + id, + user, +}: GetAttackDiscoveryParams): Promise => { + const filterByUser = [ + { + nested: { + path: 'users', + query: { + bool: { + must: [ + { + match: user.profile_uid + ? { 'users.id': user.profile_uid } + : { 'users.name': user.username }, + }, + ], + }, + }, + }, + }, + ]; + try { + const response = await esClient.search({ + query: { + bool: { + must: [ + { + bool: { + should: [ + { + term: { + _id: id, + }, + }, + ], + }, + }, + ...filterByUser, + ], + }, + }, + _source: true, + ignore_unavailable: true, + index: attackDiscoveryIndex, + seq_no_primary_term: true, + }); + const attackDiscovery = transformESSearchToAttackDiscovery(response); + return attackDiscovery[0] ?? null; + } catch (err) { + logger.error(`Error fetching attack discovery: ${err} with id: ${id}`); + throw err; + } +}; diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/index.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/index.ts new file mode 100644 index 0000000000000..b8b1ef12b668c --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/index.ts @@ -0,0 +1,122 @@ +/* + * 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 { + AttackDiscoveryCreateProps, + AttackDiscoveryUpdateProps, + AttackDiscoveryResponse, +} from '@kbn/elastic-assistant-common'; +import { AuthenticatedUser } from '@kbn/core-security-common'; +import { findAttackDiscoveryByConnectorId } from './find_attack_discovery_by_connector_id'; +import { updateAttackDiscovery } from './update_attack_discovery'; +import { createAttackDiscovery } from './create_attack_discovery'; +import { getAttackDiscovery } from './get_attack_discovery'; +import { AIAssistantDataClient, AIAssistantDataClientParams } from '..'; + +type AttackDiscoveryDataClientParams = AIAssistantDataClientParams; + +export class AttackDiscoveryDataClient extends AIAssistantDataClient { + constructor(public readonly options: AttackDiscoveryDataClientParams) { + super(options); + } + + /** + * Fetches an attack discovery + * @param options + * @param options.id The existing attack discovery id. + * @param options.authenticatedUser Current authenticated user. + * @returns The attack discovery response + */ + public getAttackDiscovery = async ({ + id, + authenticatedUser, + }: { + id: string; + authenticatedUser: AuthenticatedUser; + }): Promise => { + const esClient = await this.options.elasticsearchClientPromise; + return getAttackDiscovery({ + esClient, + logger: this.options.logger, + attackDiscoveryIndex: this.indexTemplateAndPattern.alias, + id, + user: authenticatedUser, + }); + }; + + /** + * Creates an attack discovery, if given at least the "apiConfig" + * @param options + * @param options.attackDiscoveryCreate + * @param options.authenticatedUser + * @returns The Attack Discovery created + */ + public createAttackDiscovery = async ({ + attackDiscoveryCreate, + authenticatedUser, + }: { + attackDiscoveryCreate: AttackDiscoveryCreateProps; + authenticatedUser: AuthenticatedUser; + }): Promise => { + const esClient = await this.options.elasticsearchClientPromise; + return createAttackDiscovery({ + esClient, + logger: this.options.logger, + attackDiscoveryIndex: this.indexTemplateAndPattern.alias, + spaceId: this.spaceId, + user: authenticatedUser, + attackDiscoveryCreate, + }); + }; + + /** + * Find attack discovery by apiConfig connectorId + * @param options + * @param options.connectorId + * @param options.authenticatedUser + * @returns The Attack Discovery created + */ + public findAttackDiscoveryByConnectorId = async ({ + connectorId, + authenticatedUser, + }: { + connectorId: string; + authenticatedUser: AuthenticatedUser; + }): Promise => { + const esClient = await this.options.elasticsearchClientPromise; + return findAttackDiscoveryByConnectorId({ + esClient, + logger: this.options.logger, + attackDiscoveryIndex: this.indexTemplateAndPattern.alias, + connectorId, + user: authenticatedUser, + }); + }; + + /** + * Updates an attack discovery + * @param options + * @param options.attackDiscoveryUpdateProps + * @param options.authenticatedUser + */ + public updateAttackDiscovery = async ({ + attackDiscoveryUpdateProps, + authenticatedUser, + }: { + attackDiscoveryUpdateProps: AttackDiscoveryUpdateProps; + authenticatedUser: AuthenticatedUser; + }): Promise => { + const esClient = await this.options.elasticsearchClientPromise; + return updateAttackDiscovery({ + esClient, + logger: this.options.logger, + attackDiscoveryIndex: attackDiscoveryUpdateProps.backingIndex, + attackDiscoveryUpdateProps, + user: authenticatedUser, + }); + }; +} diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/transforms.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/transforms.ts new file mode 100644 index 0000000000000..ce9035f66588f --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/transforms.ts @@ -0,0 +1,65 @@ +/* + * 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 { estypes } from '@elastic/elasticsearch'; +import { AttackDiscoveryResponse } from '@kbn/elastic-assistant-common'; +import { EsAttackDiscoverySchema } from './types'; + +export const transformESSearchToAttackDiscovery = ( + response: estypes.SearchResponse +): AttackDiscoveryResponse[] => { + return response.hits.hits + .filter((hit) => hit._source !== undefined) + .map((hit) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const adSchema = hit._source!; + const ad: AttackDiscoveryResponse = { + timestamp: adSchema['@timestamp'], + id: hit._id, + backingIndex: hit._index, + createdAt: adSchema.created_at, + updatedAt: adSchema.updated_at, + users: + adSchema.users?.map((user) => ({ + id: user.id, + name: user.name, + })) ?? [], + namespace: adSchema.namespace, + status: adSchema.status, + alertsContextCount: adSchema.alerts_context_count, + apiConfig: { + connectorId: adSchema.api_config.connector_id, + actionTypeId: adSchema.api_config.action_type_id, + defaultSystemPromptId: adSchema.api_config.default_system_prompt_id, + model: adSchema.api_config.model, + provider: adSchema.api_config.provider, + }, + attackDiscoveries: adSchema.attack_discoveries.map((attackDiscovery) => ({ + alertIds: attackDiscovery.alert_ids, + title: attackDiscovery.title, + detailsMarkdown: attackDiscovery.details_markdown, + entitySummaryMarkdown: attackDiscovery.entity_summary_markdown, + mitreAttackTactics: attackDiscovery.mitre_attack_tactics, + summaryMarkdown: attackDiscovery.summary_markdown, + timestamp: attackDiscovery.timestamp, + })), + replacements: adSchema.replacements?.reduce((acc: Record, r) => { + acc[r.uuid] = r.value; + return acc; + }, {}), + generationIntervals: + adSchema.generation_intervals?.map((interval) => ({ + date: interval.date, + durationMs: interval.duration_ms, + })) ?? [], + averageIntervalMs: adSchema.average_interval_ms ?? 0, + failureReason: adSchema.failure_reason, + }; + + return ad; + }); +}; diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/types.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/types.ts new file mode 100644 index 0000000000000..6257be7f82431 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/types.ts @@ -0,0 +1,76 @@ +/* + * 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 { AttackDiscoveryStatus, Provider } from '@kbn/elastic-assistant-common'; +import { EsReplacementSchema } from '../conversations/types'; + +export interface EsAttackDiscoverySchema { + '@timestamp': string; + id: string; + created_at: string; + namespace: string; + attack_discoveries: Array<{ + alert_ids: string[]; + title: string; + timestamp: string; + details_markdown: string; + entity_summary_markdown: string; + mitre_attack_tactics?: string[]; + summary_markdown: string; + id?: string; + }>; + failure_reason?: string; + api_config: { + connector_id: string; + action_type_id: string; + default_system_prompt_id?: string; + provider?: Provider; + model?: string; + }; + alerts_context_count?: number; + replacements?: EsReplacementSchema[]; + status: AttackDiscoveryStatus; + updated_at?: string; + users?: Array<{ + id?: string; + name?: string; + }>; + average_interval_ms?: number; + generation_intervals?: Array<{ date: string; duration_ms: number }>; +} + +export interface CreateAttackDiscoverySchema { + '@timestamp'?: string; + created_at: string; + id?: string | undefined; + attack_discoveries: Array<{ + alert_ids: string[]; + title: string; + timestamp: string; + details_markdown: string; + entity_summary_markdown: string; + mitre_attack_tactics?: string[]; + summary_markdown: string; + id?: string; + }>; + api_config: { + action_type_id: string; + connector_id: string; + default_system_prompt_id?: string; + provider?: Provider; + model?: string; + }; + alerts_context_count?: number; + replacements?: EsReplacementSchema[]; + status: AttackDiscoveryStatus; + users: Array<{ + id?: string; + name?: string; + }>; + updated_at?: string; + namespace: string; +} diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/update_attack_discovery.test.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/update_attack_discovery.test.ts new file mode 100644 index 0000000000000..df8615d0336cf --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/update_attack_discovery.test.ts @@ -0,0 +1,183 @@ +/* + * 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 { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { loggerMock } from '@kbn/logging-mocks'; +import { getAttackDiscovery } from './get_attack_discovery'; +import { updateAttackDiscovery } from './update_attack_discovery'; +import { + AttackDiscoveryResponse, + AttackDiscoveryStatus, + AttackDiscoveryUpdateProps, +} from '@kbn/elastic-assistant-common'; +import { AuthenticatedUser } from '@kbn/security-plugin/common'; +jest.mock('./get_attack_discovery'); +const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); +const mockLogger = loggerMock.create(); +const user = { + username: 'test_user', + profile_uid: '1234', + authentication_realm: { + type: 'my_realm_type', + name: 'my_realm_name', + }, +} as AuthenticatedUser; +const updateProps: AttackDiscoveryUpdateProps = { + id: 'existing-id', + backingIndex: 'attack-discovery-index', + status: 'succeeded' as AttackDiscoveryStatus, + attackDiscoveries: [ + { + alertIds: ['alert-1'], + title: 'Updated Title', + detailsMarkdown: '# Updated Details', + entitySummaryMarkdown: '# Updated Summary', + timestamp: '2024-06-07T21:19:08.090Z', + id: 'existing-id', + mitreAttackTactics: ['T1234'], + summaryMarkdown: '# Updated Summary', + }, + ], +}; +const mockRequest = { + esClient: mockEsClient, + attackDiscoveryIndex: 'attack-discovery-index', + attackDiscoveryUpdateProps: updateProps, + user, + logger: mockLogger, +}; + +const existingAttackDiscovery: AttackDiscoveryResponse = { + id: 'existing-id', + backingIndex: 'attack-discovery-index', + timestamp: '2024-06-07T18:56:17.357Z', + createdAt: '2024-06-07T18:56:17.357Z', + users: [ + { + id: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + name: 'elastic', + }, + ], + status: 'running', + apiConfig: { + actionTypeId: '.gen-ai', + connectorId: 'my-gpt4o-ai', + }, + attackDiscoveries: [], + updatedAt: '2024-06-07T21:19:08.090Z', + replacements: { + 'f19e1a0a-de3b-496c-8ace-dd91229e1084': 'root', + }, + namespace: 'default', + generationIntervals: [ + { + date: '2024-06-07T21:19:08.089Z', + durationMs: 110906, + }, + { + date: '2024-06-07T20:04:35.715Z', + durationMs: 104593, + }, + { + date: '2024-06-07T18:58:27.880Z', + durationMs: 130526, + }, + ], + alertsContextCount: 20, + averageIntervalMs: 115341, +}; + +const mockGetDiscovery = getAttackDiscovery as jest.Mock; + +describe('updateAttackDiscovery', () => { + const date = '2024-03-28T22:27:28.000Z'; + beforeAll(() => { + jest.useFakeTimers(); + }); + + beforeEach(() => { + jest.setSystemTime(new Date(date)); + jest.clearAllMocks(); + mockGetDiscovery.mockResolvedValue(existingAttackDiscovery); + }); + + it('should update attack discovery successfully', async () => { + const response = await updateAttackDiscovery(mockRequest); + expect(response).not.toBeNull(); + expect(response!.id).toEqual('existing-id'); + expect(mockEsClient.update).toHaveBeenCalledTimes(1); + expect(mockEsClient.update).toHaveBeenCalledWith({ + refresh: 'wait_for', + index: 'attack-discovery-index', + id: 'existing-id', + doc: { + attack_discoveries: [ + { + id: 'existing-id', + alert_ids: ['alert-1'], + title: 'Updated Title', + details_markdown: '# Updated Details', + entity_summary_markdown: '# Updated Summary', + mitre_attack_tactics: ['T1234'], + summary_markdown: '# Updated Summary', + timestamp: date, + }, + ], + id: 'existing-id', + status: 'succeeded', + updated_at: date, + }, + }); + expect(mockGetDiscovery).toHaveBeenCalledTimes(1); + const { attackDiscoveryUpdateProps, ...rest } = mockRequest; + expect(mockGetDiscovery).toHaveBeenCalledWith({ + ...rest, + id: attackDiscoveryUpdateProps.id, + }); + }); + + it('should not update attack_discoveries if none are present', async () => { + const { attackDiscoveries, ...rest } = mockRequest.attackDiscoveryUpdateProps; + const response = await updateAttackDiscovery({ + ...mockRequest, + attackDiscoveryUpdateProps: rest, + }); + + expect(response).not.toBeNull(); + expect(response!.id).toEqual('existing-id'); + expect(mockEsClient.update).toHaveBeenCalledTimes(1); + expect(mockEsClient.update).toHaveBeenCalledWith({ + refresh: 'wait_for', + index: 'attack-discovery-index', + id: 'existing-id', + doc: { + id: 'existing-id', + status: 'succeeded', + updated_at: date, + }, + }); + expect(mockGetDiscovery).toHaveBeenCalledTimes(1); + const { attackDiscoveryUpdateProps, ...rest2 } = mockRequest; + expect(mockGetDiscovery).toHaveBeenCalledWith({ + ...rest2, + id: attackDiscoveryUpdateProps.id, + }); + }); + + it('should throw error on elasticsearch update failure', async () => { + const error = new Error('Elasticsearch update error'); + mockEsClient.update.mockRejectedValueOnce(error); + + await expect(updateAttackDiscovery(mockRequest)).rejects.toThrowError(error); + + expect(mockEsClient.update).toHaveBeenCalledTimes(1); + expect(mockLogger.warn).toHaveBeenCalledTimes(1); + expect(mockLogger.warn).toHaveBeenCalledWith( + `Error updating attackDiscovery: ${error} by ID: existing-id` + ); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/update_attack_discovery.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/update_attack_discovery.ts new file mode 100644 index 0000000000000..8db6a2ed2968a --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_data_clients/attack_discovery/update_attack_discovery.ts @@ -0,0 +1,155 @@ +/* + * 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 { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { + AttackDiscoveryResponse, + AttackDiscoveryStatus, + AttackDiscoveryUpdateProps, + Provider, + UUID, +} from '@kbn/elastic-assistant-common'; +import { AuthenticatedUser } from '@kbn/security-plugin/common'; +import * as uuid from 'uuid'; +import { EsReplacementSchema } from '../conversations/types'; +import { getAttackDiscovery } from './get_attack_discovery'; + +export interface UpdateAttackDiscoverySchema { + id: UUID; + '@timestamp'?: string; + attack_discoveries?: Array<{ + alert_ids: string[]; + title: string; + timestamp: string; + details_markdown: string; + entity_summary_markdown: string; + mitre_attack_tactics?: string[]; + summary_markdown: string; + id?: string; + }>; + api_config?: { + action_type_id?: string; + connector_id?: string; + default_system_prompt_id?: string; + provider?: Provider; + model?: string; + }; + alerts_context_count?: number; + average_interval_ms?: number; + generation_intervals?: Array<{ date: string; duration_ms: number }>; + replacements?: EsReplacementSchema[]; + status: AttackDiscoveryStatus; + updated_at?: string; + failure_reason?: string; +} + +export interface UpdateAttackDiscoveryParams { + esClient: ElasticsearchClient; + logger: Logger; + user: AuthenticatedUser; + attackDiscoveryIndex: string; + attackDiscoveryUpdateProps: AttackDiscoveryUpdateProps; +} + +export const updateAttackDiscovery = async ({ + esClient, + logger, + attackDiscoveryIndex, + attackDiscoveryUpdateProps, + user, +}: UpdateAttackDiscoveryParams): Promise => { + const updatedAt = new Date().toISOString(); + const params = transformToUpdateScheme(updatedAt, attackDiscoveryUpdateProps); + try { + await esClient.update({ + refresh: 'wait_for', + index: attackDiscoveryIndex, + id: params.id, + doc: params, + }); + + const updatedAttackDiscovery = await getAttackDiscovery({ + esClient, + attackDiscoveryIndex, + id: params.id, + logger, + user, + }); + + return updatedAttackDiscovery; + } catch (err) { + logger.warn(`Error updating attackDiscovery: ${err} by ID: ${params.id}`); + throw err; + } +}; + +export const transformToUpdateScheme = ( + updatedAt: string, + { + alertsContextCount, + apiConfig, + attackDiscoveries, + failureReason, + generationIntervals, + id, + replacements, + status, + }: AttackDiscoveryUpdateProps +): UpdateAttackDiscoverySchema => { + const averageIntervalMsObj = + generationIntervals && generationIntervals.length > 0 + ? { + average_interval_ms: Math.trunc( + generationIntervals.reduce((acc, interval) => acc + interval.durationMs, 0) / + generationIntervals.length + ), + generation_intervals: generationIntervals.map((interval) => ({ + date: interval.date, + duration_ms: interval.durationMs, + })), + } + : {}; + return { + alerts_context_count: alertsContextCount, + ...(apiConfig + ? { + api_config: { + action_type_id: apiConfig.actionTypeId, + connector_id: apiConfig.connectorId, + default_system_prompt_id: apiConfig.defaultSystemPromptId, + model: apiConfig.model, + provider: apiConfig.provider, + }, + } + : {}), + ...(attackDiscoveries + ? { + attack_discoveries: attackDiscoveries.map((attackDiscovery) => ({ + id: attackDiscovery.id ?? uuid.v4(), + alert_ids: attackDiscovery.alertIds, + title: attackDiscovery.title, + details_markdown: attackDiscovery.detailsMarkdown, + entity_summary_markdown: attackDiscovery.entitySummaryMarkdown, + mitre_attack_tactics: attackDiscovery.mitreAttackTactics, + summary_markdown: attackDiscovery.summaryMarkdown, + timestamp: updatedAt, + })), + } + : {}), + failure_reason: failureReason, + id, + replacements: replacements + ? Object.keys(replacements).map((key) => ({ + uuid: key, + value: replacements[key], + })) + : undefined, + status, + updated_at: updatedAt, + ...averageIntervalMsObj, + }; +}; diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_service/index.test.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_service/index.test.ts index dbdc01dcf9e57..adf31630fdf04 100644 --- a/x-pack/plugins/elastic_assistant/server/ai_assistant_service/index.test.ts +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_service/index.test.ts @@ -135,12 +135,18 @@ describe('AI Assistant Service', () => { ); expect(assistantService.isInitialized()).toEqual(true); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(3); - const componentTemplate = clusterClient.cluster.putComponentTemplate.mock.calls[0][0]; - expect(componentTemplate.name).toEqual( - '.kibana-elastic-ai-assistant-component-template-conversations' - ); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(4); + + const expectedTemplates = [ + '.kibana-elastic-ai-assistant-component-template-conversations', + '.kibana-elastic-ai-assistant-component-template-prompts', + '.kibana-elastic-ai-assistant-component-template-anonymization-fields', + '.kibana-elastic-ai-assistant-component-template-attack-discovery', + ]; + expectedTemplates.forEach((t, i) => { + expect(clusterClient.cluster.putComponentTemplate.mock.calls[i][0].name).toEqual(t); + }); }); test('should log error and set initialized to false if creating/updating common component template throws error', async () => { @@ -628,7 +634,19 @@ describe('AI Assistant Service', () => { 'AI Assistant service initialized', async () => assistantService.isInitialized() === true ); - expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(5); + expect(clusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(6); + + const expectedTemplates = [ + '.kibana-elastic-ai-assistant-component-template-conversations', + '.kibana-elastic-ai-assistant-component-template-conversations', + '.kibana-elastic-ai-assistant-component-template-conversations', + '.kibana-elastic-ai-assistant-component-template-prompts', + '.kibana-elastic-ai-assistant-component-template-anonymization-fields', + '.kibana-elastic-ai-assistant-component-template-attack-discovery', + ]; + expectedTemplates.forEach((t, i) => { + expect(clusterClient.cluster.putComponentTemplate.mock.calls[i][0].name).toEqual(t); + }); }); test('should retry updating index template for transient ES errors', async () => { @@ -649,7 +667,18 @@ describe('AI Assistant Service', () => { async () => (await getSpaceResourcesInitialized(assistantService)) === true ); - expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(5); + expect(clusterClient.indices.putIndexTemplate).toHaveBeenCalledTimes(6); + const expectedTemplates = [ + '.kibana-elastic-ai-assistant-index-template-conversations', + '.kibana-elastic-ai-assistant-index-template-conversations', + '.kibana-elastic-ai-assistant-index-template-conversations', + '.kibana-elastic-ai-assistant-index-template-prompts', + '.kibana-elastic-ai-assistant-index-template-anonymization-fields', + '.kibana-elastic-ai-assistant-index-template-attack-discovery', + ]; + expectedTemplates.forEach((t, i) => { + expect(clusterClient.indices.putIndexTemplate.mock.calls[i][0].name).toEqual(t); + }); }); test('should retry updating index settings for existing indices for transient ES errors', async () => { @@ -669,7 +698,7 @@ describe('AI Assistant Service', () => { async () => (await getSpaceResourcesInitialized(assistantService)) === true ); - expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(5); + expect(clusterClient.indices.putSettings).toHaveBeenCalledTimes(6); }); test('should retry updating index mappings for existing indices for transient ES errors', async () => { @@ -689,7 +718,7 @@ describe('AI Assistant Service', () => { async () => (await getSpaceResourcesInitialized(assistantService)) === true ); - expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(5); + expect(clusterClient.indices.putMapping).toHaveBeenCalledTimes(6); }); test('should retry creating concrete index for transient ES errors', async () => { diff --git a/x-pack/plugins/elastic_assistant/server/ai_assistant_service/index.ts b/x-pack/plugins/elastic_assistant/server/ai_assistant_service/index.ts index 619d9e9bca256..351508da01a5a 100644 --- a/x-pack/plugins/elastic_assistant/server/ai_assistant_service/index.ts +++ b/x-pack/plugins/elastic_assistant/server/ai_assistant_service/index.ts @@ -12,6 +12,7 @@ import type { TaskManagerSetupContract } from '@kbn/task-manager-plugin/server'; import type { MlPluginSetup } from '@kbn/ml-plugin/server'; import { AuthenticatedUser } from '@kbn/security-plugin/server'; import { Subject } from 'rxjs'; +import { attackDiscoveryFieldMap } from '../ai_assistant_data_clients/attack_discovery/field_maps_configuration'; import { getDefaultAnonymizationFields } from '../../common/anonymization'; import { AssistantResourceNames, GetElser } from '../types'; import { AIAssistantConversationsDataClient } from '../ai_assistant_data_clients/conversations'; @@ -28,6 +29,7 @@ import { assistantAnonymizationFieldsFieldMap } from '../ai_assistant_data_clien import { AIAssistantDataClient } from '../ai_assistant_data_clients'; import { knowledgeBaseFieldMap } from '../ai_assistant_data_clients/knowledge_base/field_maps_configuration'; import { AIAssistantKnowledgeBaseDataClient } from '../ai_assistant_data_clients/knowledge_base'; +import { AttackDiscoveryDataClient } from '../ai_assistant_data_clients/attack_discovery'; import { createGetElserId, createPipeline, pipelineExists } from './helpers'; const TOTAL_FIELDS_LIMIT = 2500; @@ -52,7 +54,12 @@ export interface CreateAIAssistantClientParams { } export type CreateDataStream = (params: { - resource: 'anonymizationFields' | 'conversations' | 'knowledgeBase' | 'prompts'; + resource: + | 'anonymizationFields' + | 'conversations' + | 'knowledgeBase' + | 'prompts' + | 'attackDiscovery'; fieldMap: FieldMap; kibanaVersion: string; spaceId?: string; @@ -68,6 +75,7 @@ export class AIAssistantService { private knowledgeBaseDataStream: DataStreamSpacesAdapter; private promptsDataStream: DataStreamSpacesAdapter; private anonymizationFieldsDataStream: DataStreamSpacesAdapter; + private attackDiscoveryDataStream: DataStreamSpacesAdapter; private resourceInitializationHelper: ResourceInstallationHelper; private initPromise: Promise; private isKBSetupInProgress: boolean = false; @@ -95,6 +103,11 @@ export class AIAssistantService { kibanaVersion: options.kibanaVersion, fieldMap: assistantAnonymizationFieldsFieldMap, }); + this.attackDiscoveryDataStream = this.createDataStream({ + resource: 'attackDiscovery', + kibanaVersion: options.kibanaVersion, + fieldMap: attackDiscoveryFieldMap, + }); this.initPromise = this.initializeResources(); @@ -201,6 +214,12 @@ export class AIAssistantService { logger: this.options.logger, pluginStop$: this.options.pluginStop$, }); + + await this.attackDiscoveryDataStream.install({ + esClient, + logger: this.options.logger, + pluginStop$: this.options.pluginStop$, + }); } catch (error) { this.options.logger.error(`Error initializing AI assistant resources: ${error.message}`); this.initialized = false; @@ -218,24 +237,28 @@ export class AIAssistantService { knowledgeBase: getResourceName('component-template-knowledge-base'), prompts: getResourceName('component-template-prompts'), anonymizationFields: getResourceName('component-template-anonymization-fields'), + attackDiscovery: getResourceName('component-template-attack-discovery'), }, aliases: { conversations: getResourceName('conversations'), knowledgeBase: getResourceName('knowledge-base'), prompts: getResourceName('prompts'), anonymizationFields: getResourceName('anonymization-fields'), + attackDiscovery: getResourceName('attack-discovery'), }, indexPatterns: { conversations: getResourceName('conversations*'), knowledgeBase: getResourceName('knowledge-base*'), prompts: getResourceName('prompts*'), anonymizationFields: getResourceName('anonymization-fields*'), + attackDiscovery: getResourceName('attack-discovery*'), }, indexTemplate: { conversations: getResourceName('index-template-conversations'), knowledgeBase: getResourceName('index-template-knowledge-base'), prompts: getResourceName('index-template-prompts'), anonymizationFields: getResourceName('index-template-anonymization-fields'), + attackDiscovery: getResourceName('index-template-attack-discovery'), }, pipelines: { knowledgeBase: getResourceName('ingest-pipeline-knowledge-base'), @@ -338,6 +361,25 @@ export class AIAssistantService { }); } + public async createAttackDiscoveryDataClient( + opts: CreateAIAssistantClientParams + ): Promise { + const res = await this.checkResourcesInstallation(opts); + + if (res === null) { + return null; + } + + return new AttackDiscoveryDataClient({ + logger: this.options.logger.get('attackDiscovery'), + currentUser: opts.currentUser, + elasticsearchClientPromise: this.options.elasticsearchClientPromise, + indexPatternsResourceName: this.resourceNames.aliases.attackDiscovery, + kibanaVersion: this.options.kibanaVersion, + spaceId: opts.spaceId, + }); + } + public async createAIAssistantPromptsDataClient( opts: CreateAIAssistantClientParams ): Promise { diff --git a/x-pack/plugins/elastic_assistant/server/lib/telemetry/event_based_telemetry.ts b/x-pack/plugins/elastic_assistant/server/lib/telemetry/event_based_telemetry.ts index 85859b2c232b7..d938310e91d6d 100644 --- a/x-pack/plugins/elastic_assistant/server/lib/telemetry/event_based_telemetry.ts +++ b/x-pack/plugins/elastic_assistant/server/lib/telemetry/event_based_telemetry.ts @@ -163,9 +163,121 @@ export const INVOKE_ASSISTANT_ERROR_EVENT: EventTypeOpts<{ }, }; +export const ATTACK_DISCOVERY_SUCCESS_EVENT: EventTypeOpts<{ + actionTypeId: string; + alertsContextCount: number; + alertsCount: number; + configuredAlertsCount: number; + discoveriesGenerated: number; + durationMs: number; + model?: string; + provider?: string; +}> = { + eventType: 'attack_discovery_success', + schema: { + actionTypeId: { + type: 'keyword', + _meta: { + description: 'Kibana connector type', + optional: false, + }, + }, + alertsContextCount: { + type: 'integer', + _meta: { + description: 'Number of alerts sent as context to the LLM', + optional: false, + }, + }, + alertsCount: { + type: 'integer', + _meta: { + description: 'Number of unique alerts referenced in the attack discoveries', + optional: false, + }, + }, + configuredAlertsCount: { + type: 'integer', + _meta: { + description: 'Number of alerts configured by the user', + optional: false, + }, + }, + discoveriesGenerated: { + type: 'integer', + _meta: { + description: 'Quantity of attack discoveries generated', + optional: false, + }, + }, + durationMs: { + type: 'integer', + _meta: { + description: 'Duration of request in ms', + optional: false, + }, + }, + model: { + type: 'keyword', + _meta: { + description: 'LLM model', + optional: true, + }, + }, + provider: { + type: 'keyword', + _meta: { + description: 'OpenAI provider', + optional: true, + }, + }, + }, +}; + +export const ATTACK_DISCOVERY_ERROR_EVENT: EventTypeOpts<{ + actionTypeId: string; + errorMessage: string; + model?: string; + provider?: string; +}> = { + eventType: 'attack_discovery_error', + schema: { + actionTypeId: { + type: 'keyword', + _meta: { + description: 'Kibana connector type', + optional: false, + }, + }, + errorMessage: { + type: 'keyword', + _meta: { + description: 'Error message from Elasticsearch', + }, + }, + + model: { + type: 'keyword', + _meta: { + description: 'LLM model', + optional: true, + }, + }, + provider: { + type: 'keyword', + _meta: { + description: 'OpenAI provider', + optional: true, + }, + }, + }, +}; + export const events: Array> = [ KNOWLEDGE_BASE_EXECUTION_SUCCESS_EVENT, KNOWLEDGE_BASE_EXECUTION_ERROR_EVENT, INVOKE_ASSISTANT_SUCCESS_EVENT, INVOKE_ASSISTANT_ERROR_EVENT, + ATTACK_DISCOVERY_SUCCESS_EVENT, + ATTACK_DISCOVERY_ERROR_EVENT, ]; diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.test.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.test.ts new file mode 100644 index 0000000000000..66aca77f1eb8b --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.test.ts @@ -0,0 +1,107 @@ +/* + * 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 { cancelAttackDiscoveryRoute } from './cancel_attack_discovery'; + +import { AuthenticatedUser } from '@kbn/core-security-common'; +import { serverMock } from '../../__mocks__/server'; +import { requestContextMock } from '../../__mocks__/request_context'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { AttackDiscoveryDataClient } from '../../ai_assistant_data_clients/attack_discovery'; +import { transformESSearchToAttackDiscovery } from '../../ai_assistant_data_clients/attack_discovery/transforms'; +import { getAttackDiscoverySearchEsMock } from '../../__mocks__/attack_discovery_schema.mock'; +import { getCancelAttackDiscoveryRequest } from '../../__mocks__/request'; +import { updateAttackDiscoveryStatusToCanceled } from './helpers'; +jest.mock('./helpers'); + +const { clients, context } = requestContextMock.createTools(); +const server: ReturnType = serverMock.create(); +clients.core.elasticsearch.client = elasticsearchServiceMock.createScopedClusterClient(); + +const mockUser = { + username: 'my_username', + authentication_realm: { + type: 'my_realm_type', + name: 'my_realm_name', + }, +} as AuthenticatedUser; +const mockDataClient = { + findAttackDiscoveryByConnectorId: jest.fn(), + updateAttackDiscovery: jest.fn(), + createAttackDiscovery: jest.fn(), + getAttackDiscovery: jest.fn(), +} as unknown as AttackDiscoveryDataClient; +const mockCurrentAd = transformESSearchToAttackDiscovery(getAttackDiscoverySearchEsMock())[0]; +describe('cancelAttackDiscoveryRoute', () => { + beforeEach(() => { + jest.clearAllMocks(); + (updateAttackDiscoveryStatusToCanceled as jest.Mock).mockResolvedValue({ + ...mockCurrentAd, + status: 'canceled', + }); + context.elasticAssistant.getCurrentUser.mockReturnValue(mockUser); + context.elasticAssistant.getAttackDiscoveryDataClient.mockResolvedValue(mockDataClient); + + cancelAttackDiscoveryRoute(server.router); + }); + + it('should handle successful request', async () => { + const response = await server.inject( + getCancelAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + ...mockCurrentAd, + status: 'canceled', + }); + }); + + it('should handle missing authenticated user', async () => { + context.elasticAssistant.getCurrentUser.mockReturnValue(null); + const response = await server.inject( + getCancelAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + + expect(response.status).toEqual(401); + expect(response.body).toEqual({ + message: 'Authenticated user not found', + status_code: 401, + }); + }); + + it('should handle missing data client', async () => { + context.elasticAssistant.getAttackDiscoveryDataClient.mockResolvedValue(null); + const response = await server.inject( + getCancelAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + + expect(response.status).toEqual(500); + expect(response.body).toEqual({ + message: 'Attack discovery data client not initialized', + status_code: 500, + }); + }); + + it('should handle updateAttackDiscoveryStatusToCanceled error', async () => { + (updateAttackDiscoveryStatusToCanceled as jest.Mock).mockRejectedValue(new Error('Oh no!')); + const response = await server.inject( + getCancelAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + expect(response.status).toEqual(500); + expect(response.body).toEqual({ + message: { + error: 'Oh no!', + success: false, + }, + status_code: 500, + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.ts new file mode 100644 index 0000000000000..47b748c9c432a --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.ts @@ -0,0 +1,92 @@ +/* + * 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 { buildRouteValidationWithZod } from '@kbn/elastic-assistant-common/impl/schemas/common'; +import { type IKibanaResponse, IRouter, Logger } from '@kbn/core/server'; +import { + AttackDiscoveryCancelResponse, + ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, + AttackDiscoveryCancelRequestParams, +} from '@kbn/elastic-assistant-common'; +import { transformError } from '@kbn/securitysolution-es-utils'; + +import { updateAttackDiscoveryStatusToCanceled } from './helpers'; +import { ATTACK_DISCOVERY_CANCEL_BY_CONNECTOR_ID } from '../../../common/constants'; +import { buildResponse } from '../../lib/build_response'; +import { ElasticAssistantRequestHandlerContext } from '../../types'; + +export const cancelAttackDiscoveryRoute = ( + router: IRouter +) => { + router.versioned + .put({ + access: 'internal', + path: ATTACK_DISCOVERY_CANCEL_BY_CONNECTOR_ID, + options: { + tags: ['access:elasticAssistant'], + }, + }) + .addVersion( + { + version: ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, + validate: { + request: { + params: buildRouteValidationWithZod(AttackDiscoveryCancelRequestParams), + }, + response: { + 200: { + body: { custom: buildRouteValidationWithZod(AttackDiscoveryCancelResponse) }, + }, + }, + }, + }, + async ( + context, + request, + response + ): Promise> => { + const resp = buildResponse(response); + const assistantContext = await context.elasticAssistant; + const logger: Logger = assistantContext.logger; + try { + const dataClient = await assistantContext.getAttackDiscoveryDataClient(); + + const authenticatedUser = assistantContext.getCurrentUser(); + const connectorId = decodeURIComponent(request.params.connectorId); + if (authenticatedUser == null) { + return resp.error({ + body: `Authenticated user not found`, + statusCode: 401, + }); + } + if (!dataClient) { + return resp.error({ + body: `Attack discovery data client not initialized`, + statusCode: 500, + }); + } + const attackDiscovery = await updateAttackDiscoveryStatusToCanceled( + dataClient, + authenticatedUser, + connectorId + ); + + return response.ok({ + body: attackDiscovery, + }); + } catch (err) { + logger.error(err); + const error = transformError(err); + + return resp.error({ + body: { success: false, error: error.message }, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.test.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.test.ts new file mode 100644 index 0000000000000..ad5d3c4bb8d1b --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.test.ts @@ -0,0 +1,116 @@ +/* + * 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 { getAttackDiscoveryRoute } from './get_attack_discovery'; + +import { AuthenticatedUser } from '@kbn/core-security-common'; +import { serverMock } from '../../__mocks__/server'; +import { requestContextMock } from '../../__mocks__/request_context'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { AttackDiscoveryDataClient } from '../../ai_assistant_data_clients/attack_discovery'; +import { transformESSearchToAttackDiscovery } from '../../ai_assistant_data_clients/attack_discovery/transforms'; +import { getAttackDiscoverySearchEsMock } from '../../__mocks__/attack_discovery_schema.mock'; +import { getAttackDiscoveryRequest } from '../../__mocks__/request'; +jest.mock('./helpers'); + +const { clients, context } = requestContextMock.createTools(); +const server: ReturnType = serverMock.create(); +clients.core.elasticsearch.client = elasticsearchServiceMock.createScopedClusterClient(); + +const mockUser = { + username: 'my_username', + authentication_realm: { + type: 'my_realm_type', + name: 'my_realm_name', + }, +} as AuthenticatedUser; +const findAttackDiscoveryByConnectorId = jest.fn(); +const mockDataClient = { + findAttackDiscoveryByConnectorId, + updateAttackDiscovery: jest.fn(), + createAttackDiscovery: jest.fn(), + getAttackDiscovery: jest.fn(), +} as unknown as AttackDiscoveryDataClient; +const mockCurrentAd = transformESSearchToAttackDiscovery(getAttackDiscoverySearchEsMock())[0]; +describe('getAttackDiscoveryRoute', () => { + beforeEach(() => { + jest.clearAllMocks(); + context.elasticAssistant.getCurrentUser.mockReturnValue(mockUser); + context.elasticAssistant.getAttackDiscoveryDataClient.mockResolvedValue(mockDataClient); + + getAttackDiscoveryRoute(server.router); + findAttackDiscoveryByConnectorId.mockResolvedValue(mockCurrentAd); + }); + + it('should handle successful request', async () => { + const response = await server.inject( + getAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + data: mockCurrentAd, + entryExists: true, + }); + }); + + it('should handle missing authenticated user', async () => { + context.elasticAssistant.getCurrentUser.mockReturnValue(null); + const response = await server.inject( + getAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + + expect(response.status).toEqual(401); + expect(response.body).toEqual({ + message: 'Authenticated user not found', + status_code: 401, + }); + }); + + it('should handle missing data client', async () => { + context.elasticAssistant.getAttackDiscoveryDataClient.mockResolvedValue(null); + const response = await server.inject( + getAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + + expect(response.status).toEqual(500); + expect(response.body).toEqual({ + message: 'Attack discovery data client not initialized', + status_code: 500, + }); + }); + + it('should handle findAttackDiscoveryByConnectorId null response', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(null); + const response = await server.inject( + getAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual({ + entryExists: false, + }); + }); + + it('should handle findAttackDiscoveryByConnectorId error', async () => { + findAttackDiscoveryByConnectorId.mockRejectedValue(new Error('Oh no!')); + const response = await server.inject( + getAttackDiscoveryRequest('connector-id'), + requestContextMock.convertContext(context) + ); + expect(response.status).toEqual(500); + expect(response.body).toEqual({ + message: { + error: 'Oh no!', + success: false, + }, + status_code: 500, + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.ts new file mode 100644 index 0000000000000..6f3a46130357b --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.ts @@ -0,0 +1,92 @@ +/* + * 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 { buildRouteValidationWithZod } from '@kbn/elastic-assistant-common/impl/schemas/common'; +import { type IKibanaResponse, IRouter, Logger } from '@kbn/core/server'; +import { + AttackDiscoveryGetResponse, + ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, + AttackDiscoveryGetRequestParams, +} from '@kbn/elastic-assistant-common'; +import { transformError } from '@kbn/securitysolution-es-utils'; + +import { ATTACK_DISCOVERY_BY_CONNECTOR_ID } from '../../../common/constants'; +import { buildResponse } from '../../lib/build_response'; +import { ElasticAssistantRequestHandlerContext } from '../../types'; + +export const getAttackDiscoveryRoute = (router: IRouter) => { + router.versioned + .get({ + access: 'internal', + path: ATTACK_DISCOVERY_BY_CONNECTOR_ID, + options: { + tags: ['access:elasticAssistant'], + }, + }) + .addVersion( + { + version: ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, + validate: { + request: { + params: buildRouteValidationWithZod(AttackDiscoveryGetRequestParams), + }, + response: { + 200: { + body: { custom: buildRouteValidationWithZod(AttackDiscoveryGetResponse) }, + }, + }, + }, + }, + async (context, request, response): Promise> => { + const resp = buildResponse(response); + const assistantContext = await context.elasticAssistant; + const logger: Logger = assistantContext.logger; + try { + const dataClient = await assistantContext.getAttackDiscoveryDataClient(); + + const authenticatedUser = assistantContext.getCurrentUser(); + const connectorId = decodeURIComponent(request.params.connectorId); + if (authenticatedUser == null) { + return resp.error({ + body: `Authenticated user not found`, + statusCode: 401, + }); + } + if (!dataClient) { + return resp.error({ + body: `Attack discovery data client not initialized`, + statusCode: 500, + }); + } + const attackDiscovery = await dataClient.findAttackDiscoveryByConnectorId({ + connectorId, + authenticatedUser, + }); + + return response.ok({ + body: + attackDiscovery != null + ? { + data: attackDiscovery, + entryExists: true, + } + : { + entryExists: false, + }, + }); + } catch (err) { + logger.error(err); + const error = transformError(err); + + return resp.error({ + body: { success: false, error: error.message }, + statusCode: error.statusCode, + }); + } + } + ); +}; diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts new file mode 100644 index 0000000000000..086af015d76e2 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts @@ -0,0 +1,491 @@ +/* + * 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 { AuthenticatedUser } from '@kbn/core-security-common'; +import moment from 'moment'; +import { + REQUIRED_FOR_ATTACK_DISCOVERY, + addGenerationInterval, + attackDiscoveryStatus, + getAssistantToolParams, + handleToolError, + updateAttackDiscoveryStatusToCanceled, + updateAttackDiscoveryStatusToRunning, + updateAttackDiscoveries, +} from './helpers'; +import { ActionsClientLlm } from '@kbn/langchain/server'; +import { AttackDiscoveryDataClient } from '../../ai_assistant_data_clients/attack_discovery'; +import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/openai/constants'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { loggerMock } from '@kbn/logging-mocks'; +import { KibanaRequest } from '@kbn/core-http-server'; +import { + AttackDiscoveryPostRequestBody, + ExecuteConnectorRequestBody, +} from '@kbn/elastic-assistant-common'; +import { coreMock } from '@kbn/core/server/mocks'; +import { transformESSearchToAttackDiscovery } from '../../ai_assistant_data_clients/attack_discovery/transforms'; +import { getAttackDiscoverySearchEsMock } from '../../__mocks__/attack_discovery_schema.mock'; + +jest.mock('lodash/fp', () => ({ + uniq: jest.fn((arr) => Array.from(new Set(arr))), +})); + +jest.mock('@kbn/securitysolution-es-utils', () => ({ + transformError: jest.fn((err) => err), +})); +jest.mock('@kbn/langchain/server', () => ({ + ActionsClientLlm: jest.fn(), +})); +jest.mock('../evaluate/utils', () => ({ + getLangSmithTracer: jest.fn().mockReturnValue([]), +})); +jest.mock('../utils', () => ({ + getLlmType: jest.fn().mockReturnValue('llm-type'), +})); +const findAttackDiscoveryByConnectorId = jest.fn(); +const updateAttackDiscovery = jest.fn(); +const createAttackDiscovery = jest.fn(); +const getAttackDiscovery = jest.fn(); +const mockDataClient = { + findAttackDiscoveryByConnectorId, + updateAttackDiscovery, + createAttackDiscovery, + getAttackDiscovery, +} as unknown as AttackDiscoveryDataClient; +const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); +const mockLogger = loggerMock.create(); +const mockTelemetry = coreMock.createSetup().analytics; +const mockError = new Error('Test error'); +const mockAuthenticatedUser = { + username: 'user', + profile_uid: '1234', + authentication_realm: { + type: 'my_realm_type', + name: 'my_realm_name', + }, +} as AuthenticatedUser; +const mockApiConfig = { + connectorId: 'connector-id', + actionTypeId: '.bedrock', + model: 'model', + provider: OpenAiProviderType.OpenAi, +}; +const mockCurrentAd = transformESSearchToAttackDiscovery(getAttackDiscoverySearchEsMock())[0]; +describe('helpers', () => { + const date = '2024-03-28T22:27:28.000Z'; + beforeAll(() => { + jest.useFakeTimers(); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + beforeEach(() => { + jest.clearAllMocks(); + jest.setSystemTime(new Date(date)); + getAttackDiscovery.mockResolvedValue(mockCurrentAd); + updateAttackDiscovery.mockResolvedValue({}); + }); + describe('getAssistantToolParams', () => { + const mockParams = { + actions: {} as unknown as ActionsPluginStart, + alertsIndexPattern: 'alerts-*', + anonymizationFields: [{ id: '1', field: 'field1', allowed: true, anonymized: true }], + apiConfig: mockApiConfig, + esClient: mockEsClient, + connectorTimeout: 1000, + langChainTimeout: 2000, + langSmithProject: 'project', + langSmithApiKey: 'api-key', + logger: mockLogger, + latestReplacements: {}, + onNewReplacements: jest.fn(), + request: {} as KibanaRequest< + unknown, + unknown, + ExecuteConnectorRequestBody | AttackDiscoveryPostRequestBody + >, + size: 10, + }; + + it('should return formatted assistant tool params', () => { + const result = getAssistantToolParams(mockParams); + + expect(ActionsClientLlm).toHaveBeenCalledWith( + expect.objectContaining({ + connectorId: 'connector-id', + llmType: 'llm-type', + }) + ); + expect(result.anonymizationFields).toEqual([ + ...mockParams.anonymizationFields, + ...REQUIRED_FOR_ATTACK_DISCOVERY, + ]); + }); + }); + + describe('addGenerationInterval', () => { + const generationInterval = { date: '2024-01-01T00:00:00Z', durationMs: 1000 }; + const existingIntervals = [ + { date: '2024-01-02T00:00:00Z', durationMs: 2000 }, + { date: '2024-01-03T00:00:00Z', durationMs: 3000 }, + ]; + + it('should add new interval and maintain length within MAX_GENERATION_INTERVALS', () => { + const result = addGenerationInterval(existingIntervals, generationInterval); + expect(result.length).toBeLessThanOrEqual(5); + expect(result).toContain(generationInterval); + }); + + it('should remove the oldest interval if exceeding MAX_GENERATION_INTERVALS', () => { + const longExistingIntervals = [...Array(5)].map((_, i) => ({ + date: `2024-01-0${i + 2}T00:00:00Z`, + durationMs: (i + 2) * 1000, + })); + const result = addGenerationInterval(longExistingIntervals, generationInterval); + expect(result.length).toBe(5); + expect(result).not.toContain(longExistingIntervals[4]); + }); + }); + + describe('updateAttackDiscoveryStatusToRunning', () => { + it('should update existing attack discovery to running', async () => { + const existingAd = { id: 'existing-id', backingIndex: 'index' }; + findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); + updateAttackDiscovery.mockResolvedValue(existingAd); + + const result = await updateAttackDiscoveryStatusToRunning( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig + ); + + expect(findAttackDiscoveryByConnectorId).toHaveBeenCalledWith({ + connectorId: mockApiConfig.connectorId, + authenticatedUser: mockAuthenticatedUser, + }); + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: expect.objectContaining({ + status: attackDiscoveryStatus.running, + }), + authenticatedUser: mockAuthenticatedUser, + }); + expect(result).toEqual({ attackDiscoveryId: existingAd.id, currentAd: existingAd }); + }); + + it('should create a new attack discovery if none exists', async () => { + const newAd = { id: 'new-id', backingIndex: 'index' }; + findAttackDiscoveryByConnectorId.mockResolvedValue(null); + createAttackDiscovery.mockResolvedValue(newAd); + + const result = await updateAttackDiscoveryStatusToRunning( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig + ); + + expect(createAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryCreate: expect.objectContaining({ + status: attackDiscoveryStatus.running, + }), + authenticatedUser: mockAuthenticatedUser, + }); + expect(result).toEqual({ attackDiscoveryId: newAd.id, currentAd: newAd }); + }); + + it('should throw an error if updating or creating attack discovery fails', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(null); + createAttackDiscovery.mockResolvedValue(null); + + await expect( + updateAttackDiscoveryStatusToRunning(mockDataClient, mockAuthenticatedUser, mockApiConfig) + ).rejects.toThrow('Could not create attack discovery for connectorId: connector-id'); + }); + }); + + describe('updateAttackDiscoveryStatusToCanceled', () => { + const existingAd = { + id: 'existing-id', + backingIndex: 'index', + status: attackDiscoveryStatus.running, + }; + it('should update existing attack discovery to canceled', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); + updateAttackDiscovery.mockResolvedValue(existingAd); + + const result = await updateAttackDiscoveryStatusToCanceled( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig.connectorId + ); + + expect(findAttackDiscoveryByConnectorId).toHaveBeenCalledWith({ + connectorId: mockApiConfig.connectorId, + authenticatedUser: mockAuthenticatedUser, + }); + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: expect.objectContaining({ + status: attackDiscoveryStatus.canceled, + }), + authenticatedUser: mockAuthenticatedUser, + }); + expect(result).toEqual(existingAd); + }); + + it('should throw an error if attack discovery is not running', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue({ + ...existingAd, + status: attackDiscoveryStatus.succeeded, + }); + await expect( + updateAttackDiscoveryStatusToCanceled( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig.connectorId + ) + ).rejects.toThrow( + 'Connector id connector-id does not have a running attack discovery, and therefore cannot be canceled.' + ); + }); + + it('should throw an error if attack discovery does not exist', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(null); + await expect( + updateAttackDiscoveryStatusToCanceled( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig.connectorId + ) + ).rejects.toThrow('Could not find attack discovery for connector id: connector-id'); + }); + it('should throw error if updateAttackDiscovery returns null', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); + updateAttackDiscovery.mockResolvedValue(null); + + await expect( + updateAttackDiscoveryStatusToCanceled( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig.connectorId + ) + ).rejects.toThrow('Could not update attack discovery for connector id: connector-id'); + }); + }); + + describe('updateAttackDiscoveries', () => { + const mockAttackDiscoveryId = 'attack-discovery-id'; + const mockLatestReplacements = {}; + const mockRawAttackDiscoveries = JSON.stringify({ + alertsContextCount: 5, + attackDiscoveries: [{ alertIds: ['alert-1', 'alert-2'] }, { alertIds: ['alert-3'] }], + }); + const mockSize = 10; + const mockStartTime = moment('2024-03-28T22:25:28.000Z'); + + const mockArgs = { + apiConfig: mockApiConfig, + attackDiscoveryId: mockAttackDiscoveryId, + authenticatedUser: mockAuthenticatedUser, + dataClient: mockDataClient, + latestReplacements: mockLatestReplacements, + logger: mockLogger, + rawAttackDiscoveries: mockRawAttackDiscoveries, + size: mockSize, + startTime: mockStartTime, + telemetry: mockTelemetry, + }; + + it('should update attack discoveries and report success telemetry', async () => { + await updateAttackDiscoveries(mockArgs); + + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: { + alertsContextCount: 5, + attackDiscoveries: [{ alertIds: ['alert-1', 'alert-2'] }, { alertIds: ['alert-3'] }], + status: attackDiscoveryStatus.succeeded, + id: mockAttackDiscoveryId, + replacements: mockLatestReplacements, + backingIndex: mockCurrentAd.backingIndex, + generationIntervals: [{ date, durationMs: 120000 }, ...mockCurrentAd.generationIntervals], + }, + authenticatedUser: mockAuthenticatedUser, + }); + + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_success', { + actionTypeId: mockApiConfig.actionTypeId, + alertsContextCount: 5, + alertsCount: 3, + configuredAlertsCount: mockSize, + discoveriesGenerated: 2, + durationMs: 120000, + model: mockApiConfig.model, + provider: mockApiConfig.provider, + }); + }); + + it('should update attack discoveries without generation interval if no discoveries are found', async () => { + const noDiscoveriesRaw = JSON.stringify({ + alertsContextCount: 0, + attackDiscoveries: [], + }); + + await updateAttackDiscoveries({ + ...mockArgs, + rawAttackDiscoveries: noDiscoveriesRaw, + }); + + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: { + alertsContextCount: 0, + attackDiscoveries: [], + status: attackDiscoveryStatus.succeeded, + id: mockAttackDiscoveryId, + replacements: mockLatestReplacements, + backingIndex: mockCurrentAd.backingIndex, + }, + authenticatedUser: mockAuthenticatedUser, + }); + + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_success', { + actionTypeId: mockApiConfig.actionTypeId, + alertsContextCount: 0, + alertsCount: 0, + configuredAlertsCount: mockSize, + discoveriesGenerated: 0, + durationMs: 120000, + model: mockApiConfig.model, + provider: mockApiConfig.provider, + }); + }); + + it('should catch and log an error if raw attack discoveries is null', async () => { + await updateAttackDiscoveries({ + ...mockArgs, + rawAttackDiscoveries: null, + }); + expect(mockLogger.error).toHaveBeenCalledTimes(1); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: 'tool returned no attack discoveries', + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); + }); + + it('should return and not call updateAttackDiscovery when getAttackDiscovery returns a canceled response', async () => { + getAttackDiscovery.mockResolvedValue({ + ...mockCurrentAd, + status: attackDiscoveryStatus.canceled, + }); + await updateAttackDiscoveries(mockArgs); + + expect(mockLogger.error).not.toHaveBeenCalled(); + expect(updateAttackDiscovery).not.toHaveBeenCalled(); + }); + + it('should log the error and report telemetry when getAttackDiscovery rejects', async () => { + getAttackDiscovery.mockRejectedValue(mockError); + await updateAttackDiscoveries(mockArgs); + + expect(mockLogger.error).toHaveBeenCalledWith(mockError); + expect(updateAttackDiscovery).not.toHaveBeenCalled(); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: mockError.message, + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); + }); + }); + + describe('handleToolError', () => { + const mockArgs = { + apiConfig: mockApiConfig, + attackDiscoveryId: 'discovery-id', + authenticatedUser: mockAuthenticatedUser, + backingIndex: 'backing-index', + dataClient: mockDataClient, + err: mockError, + latestReplacements: {}, + logger: mockLogger, + telemetry: mockTelemetry, + }; + + it('should log the error and update attack discovery status to failed', async () => { + await handleToolError(mockArgs); + + expect(mockLogger.error).toHaveBeenCalledWith(mockError); + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: { + status: attackDiscoveryStatus.failed, + attackDiscoveries: [], + backingIndex: 'foo', + failureReason: 'Test error', + id: 'discovery-id', + replacements: {}, + }, + authenticatedUser: mockArgs.authenticatedUser, + }); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: mockError.message, + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); + }); + + it('should log the error and report telemetry when updateAttackDiscovery rejects', async () => { + updateAttackDiscovery.mockRejectedValue(mockError); + await handleToolError(mockArgs); + + expect(mockLogger.error).toHaveBeenCalledWith(mockError); + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: { + status: attackDiscoveryStatus.failed, + attackDiscoveries: [], + backingIndex: 'foo', + failureReason: 'Test error', + id: 'discovery-id', + replacements: {}, + }, + authenticatedUser: mockArgs.authenticatedUser, + }); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: mockError.message, + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); + }); + + it('should return and not call updateAttackDiscovery when getAttackDiscovery returns a canceled response', async () => { + getAttackDiscovery.mockResolvedValue({ + ...mockCurrentAd, + status: attackDiscoveryStatus.canceled, + }); + await handleToolError(mockArgs); + + expect(mockTelemetry.reportEvent).not.toHaveBeenCalled(); + expect(updateAttackDiscovery).not.toHaveBeenCalled(); + }); + + it('should log the error and report telemetry when getAttackDiscovery rejects', async () => { + getAttackDiscovery.mockRejectedValue(mockError); + await handleToolError(mockArgs); + + expect(mockLogger.error).toHaveBeenCalledWith(mockError); + expect(updateAttackDiscovery).not.toHaveBeenCalled(); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: mockError.message, + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts index 4f916be8105d4..9dca7ee46cbda 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts @@ -5,19 +5,36 @@ * 2.0. */ -import { KibanaRequest } from '@kbn/core/server'; -import { Logger } from '@kbn/logging'; +import { AnalyticsServiceSetup, AuthenticatedUser, KibanaRequest, Logger } from '@kbn/core/server'; import { ElasticsearchClient } from '@kbn/core-elasticsearch-server'; import { + ApiConfig, + AttackDiscovery, AttackDiscoveryPostRequestBody, + AttackDiscoveryResponse, + AttackDiscoveryStatus, ExecuteConnectorRequestBody, + GenerationInterval, Replacements, } from '@kbn/elastic-assistant-common'; import { AnonymizationFieldResponse } from '@kbn/elastic-assistant-common/impl/schemas/anonymization_fields/bulk_crud_anonymization_fields_route.gen'; import { v4 as uuidv4 } from 'uuid'; import { ActionsClientLlm } from '@kbn/langchain/server'; +import { Moment } from 'moment'; +import { transformError } from '@kbn/securitysolution-es-utils'; +import type { PluginStartContract as ActionsPluginStart } from '@kbn/actions-plugin/server'; +import moment from 'moment/moment'; +import { uniq } from 'lodash/fp'; +import { getLangSmithTracer } from '../evaluate/utils'; +import { getLlmType } from '../utils'; +import type { GetRegisteredTools } from '../../services/app_context'; +import { + ATTACK_DISCOVERY_ERROR_EVENT, + ATTACK_DISCOVERY_SUCCESS_EVENT, +} from '../../lib/telemetry/event_based_telemetry'; import { AssistantToolParams } from '../../types'; +import { AttackDiscoveryDataClient } from '../../ai_assistant_data_clients/attack_discovery'; export const REQUIRED_FOR_ATTACK_DISCOVERY: AnonymizationFieldResponse[] = [ { @@ -35,6 +52,77 @@ export const REQUIRED_FOR_ATTACK_DISCOVERY: AnonymizationFieldResponse[] = [ ]; export const getAssistantToolParams = ({ + actions, + alertsIndexPattern, + anonymizationFields, + apiConfig, + esClient, + connectorTimeout, + langChainTimeout, + langSmithProject, + langSmithApiKey, + logger, + latestReplacements, + onNewReplacements, + request, + size, +}: { + actions: ActionsPluginStart; + alertsIndexPattern: string; + anonymizationFields?: AnonymizationFieldResponse[]; + apiConfig: ApiConfig; + esClient: ElasticsearchClient; + connectorTimeout: number; + langChainTimeout: number; + langSmithProject?: string; + langSmithApiKey?: string; + logger: Logger; + latestReplacements: Replacements; + onNewReplacements: (newReplacements: Replacements) => void; + request: KibanaRequest< + unknown, + unknown, + ExecuteConnectorRequestBody | AttackDiscoveryPostRequestBody + >; + size: number; +}) => { + const traceOptions = { + projectName: langSmithProject, + tracers: [ + ...getLangSmithTracer({ + apiKey: langSmithApiKey, + projectName: langSmithProject, + logger, + }), + ], + }; + + const llm = new ActionsClientLlm({ + actions, + connectorId: apiConfig.connectorId, + llmType: getLlmType(apiConfig.actionTypeId), + logger, + request, + temperature: 0, // zero temperature for attack discovery, because we want structured JSON output + timeout: connectorTimeout, + traceOptions, + }); + + return formatAssistantToolParams({ + alertsIndexPattern, + anonymizationFields, + esClient, + latestReplacements, + langChainTimeout, + llm, + logger, + onNewReplacements, + request, + size, + }); +}; + +const formatAssistantToolParams = ({ alertsIndexPattern, anonymizationFields, esClient, @@ -75,3 +163,254 @@ export const getAssistantToolParams = ({ request, size, }); + +export const attackDiscoveryStatus: { [k: string]: AttackDiscoveryStatus } = { + canceled: 'canceled', + failed: 'failed', + running: 'running', + succeeded: 'succeeded', +}; +const MAX_GENERATION_INTERVALS = 5; + +export const addGenerationInterval = ( + generationIntervals: GenerationInterval[], + generationInterval: GenerationInterval +): GenerationInterval[] => { + const newGenerationIntervals = [generationInterval, ...generationIntervals]; + + if (newGenerationIntervals.length > MAX_GENERATION_INTERVALS) { + return newGenerationIntervals.slice(0, MAX_GENERATION_INTERVALS); // Return the first MAX_GENERATION_INTERVALS items + } + + return newGenerationIntervals; +}; + +export const updateAttackDiscoveryStatusToRunning = async ( + dataClient: AttackDiscoveryDataClient, + authenticatedUser: AuthenticatedUser, + apiConfig: ApiConfig +): Promise<{ + currentAd: AttackDiscoveryResponse; + attackDiscoveryId: string; +}> => { + const foundAttackDiscovery = await dataClient?.findAttackDiscoveryByConnectorId({ + connectorId: apiConfig.connectorId, + authenticatedUser, + }); + const currentAd = foundAttackDiscovery + ? await dataClient?.updateAttackDiscovery({ + attackDiscoveryUpdateProps: { + backingIndex: foundAttackDiscovery.backingIndex, + id: foundAttackDiscovery.id, + status: attackDiscoveryStatus.running, + }, + authenticatedUser, + }) + : await dataClient?.createAttackDiscovery({ + attackDiscoveryCreate: { + apiConfig, + attackDiscoveries: [], + status: attackDiscoveryStatus.running, + }, + authenticatedUser, + }); + + if (!currentAd) { + throw new Error( + `Could not ${foundAttackDiscovery ? 'update' : 'create'} attack discovery for connectorId: ${ + apiConfig.connectorId + }` + ); + } + + return { + attackDiscoveryId: currentAd.id, + currentAd, + }; +}; + +export const updateAttackDiscoveryStatusToCanceled = async ( + dataClient: AttackDiscoveryDataClient, + authenticatedUser: AuthenticatedUser, + connectorId: string +): Promise => { + const foundAttackDiscovery = await dataClient?.findAttackDiscoveryByConnectorId({ + connectorId, + authenticatedUser, + }); + if (foundAttackDiscovery == null) { + throw new Error(`Could not find attack discovery for connector id: ${connectorId}`); + } + if (foundAttackDiscovery.status !== 'running') { + throw new Error( + `Connector id ${connectorId} does not have a running attack discovery, and therefore cannot be canceled.` + ); + } + const updatedAttackDiscovery = await dataClient?.updateAttackDiscovery({ + attackDiscoveryUpdateProps: { + backingIndex: foundAttackDiscovery.backingIndex, + id: foundAttackDiscovery.id, + status: attackDiscoveryStatus.canceled, + }, + authenticatedUser, + }); + + if (!updatedAttackDiscovery) { + throw new Error(`Could not update attack discovery for connector id: ${connectorId}`); + } + + return updatedAttackDiscovery; +}; + +const getDataFromJSON = (adStringified: string) => { + const { alertsContextCount, attackDiscoveries } = JSON.parse(adStringified); + return { alertsContextCount, attackDiscoveries }; +}; + +export const updateAttackDiscoveries = async ({ + apiConfig, + attackDiscoveryId, + authenticatedUser, + dataClient, + latestReplacements, + logger, + rawAttackDiscoveries, + size, + startTime, + telemetry, +}: { + apiConfig: ApiConfig; + attackDiscoveryId: string; + authenticatedUser: AuthenticatedUser; + dataClient: AttackDiscoveryDataClient; + latestReplacements: Replacements; + logger: Logger; + rawAttackDiscoveries: string | null; + size: number; + startTime: Moment; + telemetry: AnalyticsServiceSetup; +}) => { + try { + if (rawAttackDiscoveries == null) { + throw new Error('tool returned no attack discoveries'); + } + const currentAd = await dataClient.getAttackDiscovery({ + id: attackDiscoveryId, + authenticatedUser, + }); + if (currentAd === null || currentAd?.status === 'canceled') { + return; + } + const endTime = moment(); + const durationMs = endTime.diff(startTime); + const { alertsContextCount, attackDiscoveries } = getDataFromJSON(rawAttackDiscoveries); + const updateProps = { + alertsContextCount, + attackDiscoveries, + status: attackDiscoveryStatus.succeeded, + ...(alertsContextCount === 0 || attackDiscoveries === 0 + ? {} + : { + generationIntervals: addGenerationInterval(currentAd.generationIntervals, { + durationMs, + date: new Date().toISOString(), + }), + }), + id: attackDiscoveryId, + replacements: latestReplacements, + backingIndex: currentAd.backingIndex, + }; + + await dataClient.updateAttackDiscovery({ + attackDiscoveryUpdateProps: updateProps, + authenticatedUser, + }); + telemetry.reportEvent(ATTACK_DISCOVERY_SUCCESS_EVENT.eventType, { + actionTypeId: apiConfig.actionTypeId, + alertsContextCount: updateProps.alertsContextCount, + alertsCount: uniq( + updateProps.attackDiscoveries.flatMap( + (attackDiscovery: AttackDiscovery) => attackDiscovery.alertIds + ) + ).length, + configuredAlertsCount: size, + discoveriesGenerated: updateProps.attackDiscoveries.length, + durationMs, + model: apiConfig.model, + provider: apiConfig.provider, + }); + } catch (updateErr) { + logger.error(updateErr); + const updateError = transformError(updateErr); + telemetry.reportEvent(ATTACK_DISCOVERY_ERROR_EVENT.eventType, { + actionTypeId: apiConfig.actionTypeId, + errorMessage: updateError.message, + model: apiConfig.model, + provider: apiConfig.provider, + }); + } +}; + +export const handleToolError = async ({ + apiConfig, + attackDiscoveryId, + authenticatedUser, + dataClient, + err, + latestReplacements, + logger, + telemetry, +}: { + apiConfig: ApiConfig; + attackDiscoveryId: string; + authenticatedUser: AuthenticatedUser; + dataClient: AttackDiscoveryDataClient; + err: Error; + latestReplacements: Replacements; + logger: Logger; + telemetry: AnalyticsServiceSetup; +}) => { + try { + logger.error(err); + const error = transformError(err); + const currentAd = await dataClient.getAttackDiscovery({ + id: attackDiscoveryId, + authenticatedUser, + }); + + if (currentAd === null || currentAd?.status === 'canceled') { + return; + } + await dataClient.updateAttackDiscovery({ + attackDiscoveryUpdateProps: { + attackDiscoveries: [], + status: attackDiscoveryStatus.failed, + id: attackDiscoveryId, + replacements: latestReplacements, + backingIndex: currentAd.backingIndex, + failureReason: error.message, + }, + authenticatedUser, + }); + telemetry.reportEvent(ATTACK_DISCOVERY_ERROR_EVENT.eventType, { + actionTypeId: apiConfig.actionTypeId, + errorMessage: error.message, + model: apiConfig.model, + provider: apiConfig.provider, + }); + } catch (updateErr) { + const updateError = transformError(updateErr); + telemetry.reportEvent(ATTACK_DISCOVERY_ERROR_EVENT.eventType, { + actionTypeId: apiConfig.actionTypeId, + errorMessage: updateError.message, + model: apiConfig.model, + provider: apiConfig.provider, + }); + } +}; + +export const getAssistantTool = (getRegisteredTools: GetRegisteredTools, pluginName: string) => { + // get the attack discovery tool: + const assistantTools = getRegisteredTools(pluginName); + return assistantTools.find((tool) => tool.id === 'attack-discovery'); +}; diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/post_attack_discovery.test.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/post_attack_discovery.test.ts new file mode 100644 index 0000000000000..9ecfb5c2af333 --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/post_attack_discovery.test.ts @@ -0,0 +1,142 @@ +/* + * 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 { AuthenticatedUser } from '@kbn/core-security-common'; +import { postAttackDiscoveryRoute } from './post_attack_discovery'; +import { serverMock } from '../../__mocks__/server'; +import { requestContextMock } from '../../__mocks__/request_context'; +import { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; +import { AttackDiscoveryDataClient } from '../../ai_assistant_data_clients/attack_discovery'; +import { transformESSearchToAttackDiscovery } from '../../ai_assistant_data_clients/attack_discovery/transforms'; +import { getAttackDiscoverySearchEsMock } from '../../__mocks__/attack_discovery_schema.mock'; +import { postAttackDiscoveryRequest } from '../../__mocks__/request'; +import { OpenAiProviderType } from '@kbn/stack-connectors-plugin/common/openai/constants'; +import { AttackDiscoveryPostRequestBody } from '@kbn/elastic-assistant-common'; +import { + getAssistantTool, + getAssistantToolParams, + updateAttackDiscoveryStatusToRunning, +} from './helpers'; +jest.mock('./helpers'); + +const { clients, context } = requestContextMock.createTools(); +const server: ReturnType = serverMock.create(); +clients.core.elasticsearch.client = elasticsearchServiceMock.createScopedClusterClient(); + +const mockUser = { + username: 'my_username', + authentication_realm: { + type: 'my_realm_type', + name: 'my_realm_name', + }, +} as AuthenticatedUser; +const findAttackDiscoveryByConnectorId = jest.fn(); +const mockDataClient = { + findAttackDiscoveryByConnectorId, + updateAttackDiscovery: jest.fn(), + createAttackDiscovery: jest.fn(), + getAttackDiscovery: jest.fn(), +} as unknown as AttackDiscoveryDataClient; +const mockApiConfig = { + connectorId: 'connector-id', + actionTypeId: '.bedrock', + model: 'model', + provider: OpenAiProviderType.OpenAi, +}; +const mockRequestBody: AttackDiscoveryPostRequestBody = { + subAction: 'invokeAI', + apiConfig: mockApiConfig, + alertsIndexPattern: 'alerts-*', + anonymizationFields: [], + replacements: {}, + model: 'gpt-4', + size: 20, + langSmithProject: 'langSmithProject', + langSmithApiKey: 'langSmithApiKey', +}; +const mockCurrentAd = transformESSearchToAttackDiscovery(getAttackDiscoverySearchEsMock())[0]; +const runningAd = { + ...mockCurrentAd, + status: 'running', +}; +describe('postAttackDiscoveryRoute', () => { + beforeEach(() => { + jest.clearAllMocks(); + context.elasticAssistant.getCurrentUser.mockReturnValue(mockUser); + context.elasticAssistant.getAttackDiscoveryDataClient.mockResolvedValue(mockDataClient); + postAttackDiscoveryRoute(server.router); + findAttackDiscoveryByConnectorId.mockResolvedValue(mockCurrentAd); + (getAssistantTool as jest.Mock).mockReturnValue({ getTool: jest.fn() }); + (getAssistantToolParams as jest.Mock).mockReturnValue({ tool: 'tool' }); + (updateAttackDiscoveryStatusToRunning as jest.Mock).mockResolvedValue({ + currentAd: runningAd, + attackDiscoveryId: mockCurrentAd.id, + }); + }); + + it('should handle successful request', async () => { + const response = await server.inject( + postAttackDiscoveryRequest(mockRequestBody), + requestContextMock.convertContext(context) + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual(runningAd); + }); + + it('should handle missing authenticated user', async () => { + context.elasticAssistant.getCurrentUser.mockReturnValue(null); + const response = await server.inject( + postAttackDiscoveryRequest(mockRequestBody), + requestContextMock.convertContext(context) + ); + + expect(response.status).toEqual(401); + expect(response.body).toEqual({ + message: 'Authenticated user not found', + status_code: 401, + }); + }); + + it('should handle missing data client', async () => { + context.elasticAssistant.getAttackDiscoveryDataClient.mockResolvedValue(null); + const response = await server.inject( + postAttackDiscoveryRequest(mockRequestBody), + requestContextMock.convertContext(context) + ); + + expect(response.status).toEqual(500); + expect(response.body).toEqual({ + message: 'Attack discovery data client not initialized', + status_code: 500, + }); + }); + + it('should handle assistantTool null response', async () => { + (getAssistantTool as jest.Mock).mockReturnValue(null); + const response = await server.inject( + postAttackDiscoveryRequest(mockRequestBody), + requestContextMock.convertContext(context) + ); + expect(response.status).toEqual(404); + }); + + it('should handle updateAttackDiscoveryStatusToRunning error', async () => { + (updateAttackDiscoveryStatusToRunning as jest.Mock).mockRejectedValue(new Error('Oh no!')); + const response = await server.inject( + postAttackDiscoveryRequest(mockRequestBody), + requestContextMock.convertContext(context) + ); + expect(response.status).toEqual(500); + expect(response.body).toEqual({ + message: { + error: 'Oh no!', + success: false, + }, + status_code: 500, + }); + }); +}); diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/post_attack_discovery.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/post_attack_discovery.ts index 7859d635ccb30..8ff2cd72ee36c 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/post_attack_discovery.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/post_attack_discovery.ts @@ -14,15 +14,19 @@ import { Replacements, } from '@kbn/elastic-assistant-common'; import { transformError } from '@kbn/securitysolution-es-utils'; -import { ActionsClientLlm } from '@kbn/langchain/server'; +import moment from 'moment/moment'; import { ATTACK_DISCOVERY } from '../../../common/constants'; -import { getAssistantToolParams } from './helpers'; +import { + getAssistantTool, + getAssistantToolParams, + handleToolError, + updateAttackDiscoveries, + updateAttackDiscoveryStatusToRunning, +} from './helpers'; import { DEFAULT_PLUGIN_NAME, getPluginNameFromRequest } from '../helpers'; -import { getLangSmithTracer } from '../evaluate/utils'; import { buildResponse } from '../../lib/build_response'; import { ElasticAssistantRequestHandlerContext } from '../../types'; -import { getLlmType } from '../utils'; const ROUTE_HANDLER_TIMEOUT = 10 * 60 * 1000; // 10 * 60 seconds = 10 minutes const LANG_CHAIN_TIMEOUT = ROUTE_HANDLER_TIMEOUT - 10_000; // 9 minutes 50 seconds @@ -57,13 +61,29 @@ export const postAttackDiscoveryRoute = ( }, }, async (context, request, response): Promise> => { + const startTime = moment(); // start timing the generation const resp = buildResponse(response); const assistantContext = await context.elasticAssistant; const logger: Logger = assistantContext.logger; + const telemetry = assistantContext.telemetry; try { // get the actions plugin start contract from the request context: const actions = (await context.elasticAssistant).actions; + const dataClient = await assistantContext.getAttackDiscoveryDataClient(); + const authenticatedUser = assistantContext.getCurrentUser(); + if (authenticatedUser == null) { + return resp.error({ + body: `Authenticated user not found`, + statusCode: 401, + }); + } + if (!dataClient) { + return resp.error({ + body: `Attack discovery data client not initialized`, + statusCode: 500, + }); + } const pluginName = getPluginNameFromRequest({ request, defaultPluginName: DEFAULT_PLUGIN_NAME, @@ -72,9 +92,8 @@ export const postAttackDiscoveryRoute = ( // get parameters from the request body const alertsIndexPattern = decodeURIComponent(request.body.alertsIndexPattern); - const connectorId = decodeURIComponent(request.body.connectorId); const { - actionTypeId, + apiConfig, anonymizationFields, langSmithApiKey, langSmithProject, @@ -91,42 +110,26 @@ export const postAttackDiscoveryRoute = ( latestReplacements = { ...latestReplacements, ...newReplacements }; }; - // get the attack discovery tool: - const assistantTools = (await context.elasticAssistant).getRegisteredTools(pluginName); - const assistantTool = assistantTools.find((tool) => tool.id === 'attack-discovery'); + const assistantTool = getAssistantTool( + (await context.elasticAssistant).getRegisteredTools, + pluginName + ); + if (!assistantTool) { return response.notFound(); // attack discovery tool not found } - const traceOptions = { - projectName: langSmithProject, - tracers: [ - ...getLangSmithTracer({ - apiKey: langSmithApiKey, - projectName: langSmithProject, - logger, - }), - ], - }; - - const llm = new ActionsClientLlm({ - actions, - connectorId, - llmType: getLlmType(actionTypeId), - logger, - request, - temperature: 0, // zero temperature for attack discovery, because we want structured JSON output - timeout: CONNECTOR_TIMEOUT, - traceOptions, - }); - const assistantToolParams = getAssistantToolParams({ + actions, alertsIndexPattern, anonymizationFields, + apiConfig, esClient, latestReplacements, + connectorTimeout: CONNECTOR_TIMEOUT, langChainTimeout: LANG_CHAIN_TIMEOUT, - llm, + langSmithProject, + langSmithApiKey, logger, onNewReplacements, request, @@ -135,23 +138,44 @@ export const postAttackDiscoveryRoute = ( // invoke the attack discovery tool: const toolInstance = assistantTool.getTool(assistantToolParams); - const rawAttackDiscoveries = await toolInstance?.invoke(''); - if (rawAttackDiscoveries == null) { - return response.customError({ - body: { message: 'tool returned no attack discoveries' }, - statusCode: 500, - }); - } - const { alertsContextCount, attackDiscoveries } = JSON.parse(rawAttackDiscoveries); + const { currentAd, attackDiscoveryId } = await updateAttackDiscoveryStatusToRunning( + dataClient, + authenticatedUser, + apiConfig + ); + + toolInstance + ?.invoke('') + .then((rawAttackDiscoveries: string) => + updateAttackDiscoveries({ + apiConfig, + attackDiscoveryId, + authenticatedUser, + dataClient, + latestReplacements, + logger, + rawAttackDiscoveries, + size, + startTime, + telemetry, + }) + ) + .catch((err) => + handleToolError({ + apiConfig, + attackDiscoveryId, + authenticatedUser, + dataClient, + err, + latestReplacements, + logger, + telemetry, + }) + ); return response.ok({ - body: { - alertsContextCount, - attackDiscoveries, - connector_id: connectorId, - replacements: latestReplacements, - }, + body: currentAd, }); } catch (err) { logger.error(err); diff --git a/x-pack/plugins/elastic_assistant/server/routes/index.ts b/x-pack/plugins/elastic_assistant/server/routes/index.ts index 352b91624f7fb..43e1229250f46 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/index.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/index.ts @@ -10,6 +10,7 @@ export { postActionsConnectorExecuteRoute } from './post_actions_connector_execu // Attack Discovery export { postAttackDiscoveryRoute } from './attack_discovery/post_attack_discovery'; +export { getAttackDiscoveryRoute } from './attack_discovery/get_attack_discovery'; // Knowledge Base export { deleteKnowledgeBaseRoute } from './knowledge_base/delete_knowledge_base'; diff --git a/x-pack/plugins/elastic_assistant/server/routes/register_routes.ts b/x-pack/plugins/elastic_assistant/server/routes/register_routes.ts index 374b32d6cceb5..f4da7f9f1803a 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/register_routes.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/register_routes.ts @@ -7,6 +7,8 @@ import type { Logger } from '@kbn/core/server'; +import { cancelAttackDiscoveryRoute } from './attack_discovery/cancel_attack_discovery'; +import { getAttackDiscoveryRoute } from './attack_discovery/get_attack_discovery'; import { postAttackDiscoveryRoute } from './attack_discovery/post_attack_discovery'; import { ElasticAssistantPluginRouter, GetElser } from '../types'; import { createConversationRoute } from './user_conversations/create_route'; @@ -78,5 +80,7 @@ export const registerRoutes = ( findAnonymizationFieldsRoute(router, logger); // Attack Discovery + getAttackDiscoveryRoute(router); postAttackDiscoveryRoute(router); + cancelAttackDiscoveryRoute(router); }; diff --git a/x-pack/plugins/elastic_assistant/server/routes/request_context_factory.ts b/x-pack/plugins/elastic_assistant/server/routes/request_context_factory.ts index 0a0864882df16..1bfdf33fdb146 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/request_context_factory.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/request_context_factory.ts @@ -93,6 +93,15 @@ export class RequestContextFactory implements IRequestContextFactory { }); }), + getAttackDiscoveryDataClient: memoize(() => { + const currentUser = getCurrentUser(); + return this.assistantService.createAttackDiscoveryDataClient({ + spaceId: getSpaceId(), + logger: this.logger, + currentUser, + }); + }), + getAIAssistantPromptsDataClient: memoize(() => { const currentUser = getCurrentUser(); return this.assistantService.createAIAssistantPromptsDataClient({ diff --git a/x-pack/plugins/elastic_assistant/server/types.ts b/x-pack/plugins/elastic_assistant/server/types.ts index f12bacde983df..50028bfcfd198 100755 --- a/x-pack/plugins/elastic_assistant/server/types.ts +++ b/x-pack/plugins/elastic_assistant/server/types.ts @@ -39,6 +39,7 @@ import { ActionsClientSimpleChatModel, } from '@kbn/langchain/server'; +import { AttackDiscoveryDataClient } from './ai_assistant_data_clients/attack_discovery'; import { AIAssistantConversationsDataClient } from './ai_assistant_data_clients/conversations'; import type { GetRegisteredFeatures, GetRegisteredTools } from './services/app_context'; import { AIAssistantDataClient } from './ai_assistant_data_clients'; @@ -114,6 +115,7 @@ export interface ElasticAssistantApiRequestHandlerContext { getAIAssistantKnowledgeBaseDataClient: ( initializeKnowledgeBase: boolean ) => Promise; + getAttackDiscoveryDataClient: () => Promise; getAIAssistantPromptsDataClient: () => Promise; getAIAssistantAnonymizationFieldsDataClient: () => Promise; telemetry: AnalyticsServiceSetup; @@ -148,24 +150,28 @@ export interface AssistantResourceNames { knowledgeBase: string; prompts: string; anonymizationFields: string; + attackDiscovery: string; }; indexTemplate: { conversations: string; knowledgeBase: string; prompts: string; anonymizationFields: string; + attackDiscovery: string; }; aliases: { conversations: string; knowledgeBase: string; prompts: string; anonymizationFields: string; + attackDiscovery: string; }; indexPatterns: { conversations: string; knowledgeBase: string; prompts: string; anonymizationFields: string; + attackDiscovery: string; }; pipelines: { knowledgeBase: string; diff --git a/x-pack/plugins/elastic_assistant/tsconfig.json b/x-pack/plugins/elastic_assistant/tsconfig.json index dde693653c04c..d5fef57edaf09 100644 --- a/x-pack/plugins/elastic_assistant/tsconfig.json +++ b/x-pack/plugins/elastic_assistant/tsconfig.json @@ -46,6 +46,7 @@ "@kbn/core-security-common", "@kbn/core-saved-objects-api-server", "@kbn/langchain", + "@kbn/stack-connectors-plugin", ], "exclude": [ "target/**/*", diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/index.tsx index 18df24e442072..8f2d2dede419e 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/index.tsx @@ -9,9 +9,9 @@ import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; import { css } from '@emotion/react'; import React, { useMemo } from 'react'; +import type { AttackDiscovery } from '@kbn/elastic-assistant-common'; import { Tactic } from './tactic'; import { getTacticMetadata } from '../../helpers'; -import type { AttackDiscovery } from '../../types'; interface Props { attackDiscovery: AttackDiscovery; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack/mini_attack_chain/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack/mini_attack_chain/index.tsx index 0764ca7fae644..ab41885563954 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack/mini_attack_chain/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack/mini_attack_chain/index.tsx @@ -9,9 +9,9 @@ import { css } from '@emotion/react'; import { EuiFlexGroup, EuiFlexItem, EuiText, EuiToolTip, useEuiTheme } from '@elastic/eui'; import React, { useMemo } from 'react'; +import type { AttackDiscovery } from '@kbn/elastic-assistant-common'; import { getTacticMetadata } from '../../helpers'; import { ATTACK_CHAIN_TOOLTIP } from './translations'; -import type { AttackDiscovery } from '../../types'; interface Props { attackDiscovery: AttackDiscovery; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actionable_summary/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actionable_summary/index.tsx index 7f1dbe7be3b2e..885ab18c879a7 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actionable_summary/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actionable_summary/index.tsx @@ -6,11 +6,10 @@ */ import { EuiFlexGroup, EuiFlexItem, EuiPanel } from '@elastic/eui'; -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import React, { useMemo } from 'react'; import { AttackDiscoveryMarkdownFormatter } from '../../attack_discovery_markdown_formatter'; -import type { AttackDiscovery } from '../../types'; import { ViewInAiAssistant } from '../view_in_ai_assistant'; interface Props { diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/index.tsx index 3aeba84bee02f..9dc81821917f7 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/index.tsx @@ -7,14 +7,13 @@ import { EuiFlexGroup, EuiFlexItem, EuiText, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import React from 'react'; import { AlertsBadge } from './alerts_badge'; import { MiniAttackChain } from '../../attack/mini_attack_chain'; import { TakeAction } from './take_action'; import * as i18n from './translations'; -import type { AttackDiscovery } from '../../types'; interface Props { attackDiscovery: AttackDiscovery; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/index.tsx index 5e019f6af6653..d94a177d52fdc 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import { EuiButtonEmpty, EuiContextMenuItem, @@ -19,7 +19,6 @@ import { useKibana } from '../../../../common/lib/kibana'; import { APP_ID } from '../../../../../common'; import { getAttackDiscoveryMarkdown } from '../../../get_attack_discovery_markdown/get_attack_discovery_markdown'; import * as i18n from './translations'; -import type { AttackDiscovery } from '../../../types'; import { useAddToNewCase } from '../use_add_to_case'; import { useAddToExistingCase } from '../use_add_to_existing_case'; import { useViewInAiAssistant } from '../../view_in_ai_assistant/use_view_in_ai_assistant'; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/index.tsx index daa5abd264598..2aaac0449886a 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/index.tsx @@ -7,14 +7,13 @@ import { css } from '@emotion/react'; import { EuiAccordion, EuiPanel, EuiSpacer, useEuiTheme, useGeneratedHtmlId } from '@elastic/eui'; -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import React, { useCallback, useMemo, useState } from 'react'; import { ActionableSummary } from './actionable_summary'; import { Actions } from './actions'; import { Tabs } from './tabs'; import { Title } from './title'; -import type { AttackDiscovery } from '../types'; interface Props { attackDiscovery: AttackDiscovery; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/interval/helpers.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/interval/helpers.ts deleted file mode 100644 index 934be01172e24..0000000000000 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/interval/helpers.ts +++ /dev/null @@ -1,28 +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 type { GenerationInterval } from '../../types'; - -export const encodeIntervals = ( - intervalByConnectorId: Record -): string | null => { - try { - return JSON.stringify(intervalByConnectorId, null, 2); - } catch { - return null; - } -}; - -export const decodeIntervals = ( - intervalByConnectorId: string -): Record | null => { - try { - return JSON.parse(intervalByConnectorId); - } catch { - return null; - } -}; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.tsx index d7caf0a7528c9..fc1838dad055d 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.tsx @@ -5,13 +5,12 @@ * 2.0. */ -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import { AlertConsumers } from '@kbn/rule-registry-plugin/common/technical_rule_data_field_names'; import React, { useMemo } from 'react'; import { ALERTS_TABLE_REGISTRY_CONFIG_IDS } from '../../../../../common/constants'; import { useKibana } from '../../../../common/lib/kibana'; -import type { AttackDiscovery } from '../../../types'; interface Props { attackDiscovery: AttackDiscovery; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx index e80be849de08e..bd36a047c5a1b 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer, EuiTitle, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import React, { useMemo } from 'react'; @@ -16,7 +16,6 @@ import { buildAlertsKqlFilter } from '../../../../detections/components/alerts_t import { getTacticMetadata } from '../../../helpers'; import { AttackDiscoveryMarkdownFormatter } from '../../../attack_discovery_markdown_formatter'; import * as i18n from './translations'; -import type { AttackDiscovery } from '../../../types'; import { ViewInAiAssistant } from '../../view_in_ai_assistant'; interface Props { diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.tsx index 8f74a52bdb650..2cf7905b0c3ca 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.tsx @@ -6,13 +6,12 @@ */ import { EuiSpacer } from '@elastic/eui'; -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import React from 'react'; import { AttackDiscoveryTab } from './attack_discovery_tab'; import { AlertsTab } from './alerts_tab'; import * as i18n from './translations'; -import type { AttackDiscovery } from '../../types'; interface TabInfo { content: JSX.Element; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/index.tsx index a11d63acb83bb..c11851fd15778 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/index.tsx @@ -5,12 +5,11 @@ * 2.0. */ -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import { EuiTabs, EuiTab } from '@elastic/eui'; import React, { useCallback, useMemo, useState } from 'react'; import { getTabs } from './get_tabs'; -import type { AttackDiscovery } from '../../types'; interface Props { attackDiscovery: AttackDiscovery; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/index.tsx index b3ad4590f0363..e254ce5d334b8 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/index.tsx @@ -6,12 +6,11 @@ */ import { AssistantAvatar } from '@kbn/elastic-assistant'; -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import { EuiButton, EuiButtonEmpty, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import React from 'react'; import * as i18n from './translations'; -import type { AttackDiscovery } from '../../types'; import { useViewInAiAssistant } from './use_view_in_ai_assistant'; interface Props { diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.ts index 58f66b1b2a0dd..8016e1b45b408 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.ts @@ -7,10 +7,9 @@ import { useMemo, useCallback } from 'react'; import { useAssistantOverlay } from '@kbn/elastic-assistant'; -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import { useAssistantAvailability } from '../../../assistant/use_assistant_availability'; import { getAttackDiscoveryMarkdown } from '../../get_attack_discovery_markdown/get_attack_discovery_markdown'; -import type { AttackDiscovery } from '../../types'; /** * This category is provided in the prompt context for the assistant @@ -39,7 +38,7 @@ export const useViewInAiAssistant = ({ attackDiscovery.title, // conversation title attackDiscovery.title, // description used in context pill getPromptContext, - attackDiscovery.id, // accept the UUID default for this prompt context + attackDiscovery.id ?? null, // accept the UUID default for this prompt context null, // suggestedUserPrompt null, // tooltip isAssistantEnabled, diff --git a/x-pack/plugins/security_solution/public/attack_discovery/get_attack_discovery_markdown/get_attack_discovery_markdown.ts b/x-pack/plugins/security_solution/public/attack_discovery/get_attack_discovery_markdown/get_attack_discovery_markdown.ts index e79470f670d8d..5309ef1de6bb2 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/get_attack_discovery_markdown/get_attack_discovery_markdown.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/get_attack_discovery_markdown/get_attack_discovery_markdown.ts @@ -5,10 +5,9 @@ * 2.0. */ -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscovery, Replacements } from '@kbn/elastic-assistant-common'; import { getTacticLabel, getTacticMetadata } from '../helpers'; -import type { AttackDiscovery } from '../types'; export const getMarkdownFields = (markdown: string): string => { const regex = new RegExp('{{\\s*(\\S+)\\s+(\\S+)\\s*}}', 'gm'); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/helpers.ts b/x-pack/plugins/security_solution/public/attack_discovery/helpers.ts index 2cdd1354c9b6d..731f1985c7b13 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/helpers.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/helpers.ts @@ -5,8 +5,8 @@ * 2.0. */ +import type { AttackDiscovery } from '@kbn/elastic-assistant-common'; import * as i18n from './translations'; -import type { AttackDiscovery } from './types'; export const RECONNAISSANCE = 'Reconnaissance'; export const INITIAL_ACCESS = 'Initial Access'; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_attack_discovery_telemetry/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_attack_discovery_telemetry/index.test.tsx deleted file mode 100644 index 3c8d5c40ec515..0000000000000 --- a/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_attack_discovery_telemetry/index.test.tsx +++ /dev/null @@ -1,59 +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 { renderHook } from '@testing-library/react-hooks'; -import { useAttackDiscoveryTelemetry } from '.'; -import { createTelemetryServiceMock } from '../../../common/lib/telemetry/telemetry_service.mock'; - -const reportAttackDiscoveriesGenerated = jest.fn(); -const mockedTelemetry = { - ...createTelemetryServiceMock(), - reportAttackDiscoveriesGenerated, -}; - -jest.mock('../../../common/lib/kibana', () => { - const original = jest.requireActual('../../../common/lib/kibana'); - - return { - ...original, - useKibana: () => ({ - services: { - telemetry: mockedTelemetry, - }, - }), - }; -}); - -describe('useAttackDiscoveryTelemetry', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - it('should return the expected telemetry object with tracking functions', () => { - const { result } = renderHook(() => useAttackDiscoveryTelemetry()); - expect(result.current).toHaveProperty('reportAttackDiscoveriesGenerated'); - }); - - it('Should call reportAttackDiscoveriesGenerated with appropriate actionTypeId when tracking is called', async () => { - const { result } = renderHook(() => useAttackDiscoveryTelemetry()); - await result.current.reportAttackDiscoveriesGenerated({ - actionTypeId: '.gen-ai', - model: 'gpt-4', - durationMs: 8000, - alertsCount: 20, - alertsContextCount: 25, - configuredAlertsCount: 30, - }); - expect(reportAttackDiscoveriesGenerated).toHaveBeenCalledWith({ - actionTypeId: '.gen-ai', - model: 'gpt-4', - durationMs: 8000, - alertsCount: 20, - alertsContextCount: 25, - configuredAlertsCount: 30, - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_attack_discovery_telemetry/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_attack_discovery_telemetry/index.tsx deleted file mode 100644 index a0cc331e88017..0000000000000 --- a/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_attack_discovery_telemetry/index.tsx +++ /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. - */ - -import type { ReportAttackDiscoveriesGeneratedParams } from '../../../common/lib/telemetry/events/attack_discovery/types'; -import { useKibana } from '../../../common/lib/kibana'; - -interface AttackDiscoveryTelemetry { - reportAttackDiscoveriesGenerated: (params: ReportAttackDiscoveriesGeneratedParams) => void; -} - -export const useAttackDiscoveryTelemetry = (): AttackDiscoveryTelemetry => { - const { - services: { telemetry }, - } = useKibana(); - - return { - reportAttackDiscoveriesGenerated: telemetry.reportAttackDiscoveriesGenerated, - }; -}; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_poll_api.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_poll_api.test.tsx new file mode 100644 index 0000000000000..e599bc8073425 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_poll_api.test.tsx @@ -0,0 +1,197 @@ +/* + * 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 { HttpSetupMock } from '@kbn/core-http-browser-mocks'; +import { coreMock } from '@kbn/core/public/mocks'; +import { act, renderHook } from '@testing-library/react-hooks'; +import { attackDiscoveryStatus, usePollApi } from './use_poll_api'; +import moment from 'moment/moment'; +import { kibanaMock } from '../../common/mock'; + +const http: HttpSetupMock = coreMock.createSetup().http; +const setApproximateFutureTime = jest.fn(); +const defaultProps = { http, setApproximateFutureTime, connectorId: 'my-gpt4o-ai' }; + +const mockResponse = { + timestamp: '2024-06-07T18:56:17.357Z', + createdAt: '2024-06-07T18:56:17.357Z', + users: [ + { + id: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + name: 'elastic', + }, + ], + status: 'succeeded', + apiConfig: { + actionTypeId: '.gen-ai', + connectorId: 'my-gpt4o-ai', + }, + attackDiscoveries: [ + { + summaryMarkdown: + 'A critical malware incident involving {{ host.name c1f9889f-1f6b-4abc-8e65-02de89fe1054 }} and {{ user.name 71ca47cf-082e-4d35-a8e7-6e4fa4e175da }} has been detected. The malware, identified as AppPool.vbs, was executed with high privileges and attempted to evade detection.', + id: '2204421f-bb42-4b96-a200-016a5388a029', + title: 'Critical Malware Incident on Windows Host', + mitreAttackTactics: ['Initial Access', 'Execution', 'Defense Evasion'], + alertIds: [ + '43cf228ce034aeeb89a1ef41cd7fcdef1a3db574fa5237badf1fa9eaa3425c21', + '44ae9696784b3baeee75935f889e55ce77da338241230b5c488f90a8bace43e2', + '2479b1b1007952d3b6dc26344c89f44c1bb396de56f1655eca408135b3d05af8', + ], + detailsMarkdown: 'details', + entitySummaryMarkdown: + '{{ host.name c1f9889f-1f6b-4abc-8e65-02de89fe1054 }} and {{ user.name 71ca47cf-082e-4d35-a8e7-6e4fa4e175da }} are involved in a critical malware incident.', + timestamp: '2024-06-07T20:04:35.715Z', + }, + ], + backingIndex: '1234', + updatedAt: '2024-06-07T20:04:35.715Z', + replacements: { + 'c1f9889f-1f6b-4abc-8e65-02de89fe1054': 'root', + '71ca47cf-082e-4d35-a8e7-6e4fa4e175da': 'james', + }, + namespace: 'default', + generationIntervals: [ + { + date: '2024-06-07T20:04:35.715Z', + durationMs: 104593, + }, + { + date: '2024-06-07T18:58:27.880Z', + durationMs: 130526, + }, + ], + alertsContextCount: 20, + averageIntervalMs: 117559, + id: '8e215edc-6318-4760-9566-d32f1844f9cb', +}; + +describe('usePollApi', () => { + beforeAll(() => { + jest.useFakeTimers({ legacyFakeTimers: true }); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + beforeEach(() => { + jest.clearAllMocks(); + }); + test('should render initial state with null status and data', () => { + const { result } = renderHook(() => usePollApi(defaultProps)); + expect(result.current.status).toBeNull(); + expect(result.current.data).toBeNull(); + }); + + test('should call http.fetch on pollApi call', async () => { + const { result } = renderHook(() => usePollApi(defaultProps)); + + await result.current.pollApi(); + + expect(http.fetch).toHaveBeenCalledTimes(1); + expect(http.fetch).toHaveBeenCalledWith( + '/internal/elastic_assistant/attack_discovery/my-gpt4o-ai', + { method: 'GET', version: '1' } + ); + }); + + test('should update didInitialFetch on connector change', async () => { + http.fetch.mockResolvedValue({ + entryExists: true, + data: mockResponse, + }); + const { result, rerender } = renderHook((props) => usePollApi(props), { + initialProps: defaultProps, + }); + + expect(result.current.didInitialFetch).toEqual(false); + + await act(async () => { + await result.current.pollApi(); + }); + + expect(result.current.didInitialFetch).toEqual(true); + + rerender({ ...defaultProps, connectorId: 'new-connector-id' }); + + expect(result.current.didInitialFetch).toEqual(false); + + await act(async () => { + await result.current.pollApi(); + }); + + expect(result.current.didInitialFetch).toEqual(true); + }); + + test('should update status and data on successful response', async () => { + http.fetch.mockResolvedValue({ + entryExists: true, + data: mockResponse, + }); + const { result } = renderHook(() => usePollApi(defaultProps)); + + await act(async () => { + await result.current.pollApi(); + }); + + expect(result.current.status).toBe(attackDiscoveryStatus.succeeded); + expect(result.current.data).toEqual({ ...mockResponse, connectorId: defaultProps.connectorId }); + expect(setApproximateFutureTime).toHaveBeenCalledWith( + moment(mockResponse.updatedAt).add(mockResponse.averageIntervalMs, 'milliseconds').toDate() + ); + }); + + test('should update status and data on running status and schedule next poll', async () => { + // @ts-ignore + jest.spyOn(global, 'setTimeout').mockImplementation((cb) => cb()); + http.fetch + .mockResolvedValueOnce({ + entryExists: true, + data: { ...mockResponse, attackDiscoveries: [], status: 'running' }, + }) + .mockResolvedValueOnce({ + entryExists: true, + data: { ...mockResponse, attackDiscoveries: [], status: 'running' }, + }) + .mockResolvedValueOnce({ + entryExists: true, + data: { ...mockResponse, attackDiscoveries: [], status: 'running' }, + }) + .mockResolvedValue({ + entryExists: true, + data: mockResponse, + }); + + const { result } = renderHook(() => usePollApi(defaultProps)); + + await act(async () => { + await result.current.pollApi(); + }); + // 3 from the mockResolvedValueOnce above + expect(setTimeout).toHaveBeenCalledTimes(3); + }); + test('When no connectorId and pollApi is called, should update status and data to null on error and show toast', async () => { + const addDangerMock = jest.spyOn(kibanaMock.notifications.toasts, 'addDanger'); + const { result } = renderHook(() => + usePollApi({ + http, + setApproximateFutureTime: () => {}, + toasts: kibanaMock.notifications.toasts, + }) + ); + + await result.current.pollApi(); + + expect(result.current.status).toBeNull(); + expect(result.current.data).toBeNull(); + expect(addDangerMock).toHaveBeenCalledTimes(1); + expect(addDangerMock).toHaveBeenCalledWith(new Error('Invalid connector id'), { + text: 'Invalid connector id', + title: 'Error generating attack discoveries', + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_poll_api.tsx b/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_poll_api.tsx new file mode 100644 index 0000000000000..d3821ab57f29b --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/hooks/use_poll_api.tsx @@ -0,0 +1,180 @@ +/* + * 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 { useCallback, useEffect, useRef, useState } from 'react'; +import * as uuid from 'uuid'; +import type { AttackDiscoveryStatus, AttackDiscoveryResponse } from '@kbn/elastic-assistant-common'; +import { + AttackDiscoveryCancelResponse, + AttackDiscoveryGetResponse, + ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, +} from '@kbn/elastic-assistant-common'; +import type { HttpSetup } from '@kbn/core-http-browser'; +import moment from 'moment'; +import type { IToasts } from '@kbn/core-notifications-browser'; +import { + ERROR_CANCELING_ATTACK_DISCOVERIES, + ERROR_GENERATING_ATTACK_DISCOVERIES, +} from '../pages/translations'; +import { getErrorToastText } from '../pages/helpers'; +import { replaceNewlineLiterals } from '../helpers'; + +export interface Props { + http: HttpSetup; + setApproximateFutureTime: (date: Date | null) => void; + toasts?: IToasts; + connectorId?: string; +} + +export interface AttackDiscoveryData extends AttackDiscoveryResponse { + connectorId: string; +} + +interface UsePollApi { + cancelAttackDiscovery: () => Promise; + didInitialFetch: boolean; + status: AttackDiscoveryStatus | null; + data: AttackDiscoveryData | null; + pollApi: () => void; +} + +export const usePollApi = ({ + http, + setApproximateFutureTime, + toasts, + connectorId, +}: Props): UsePollApi => { + const [status, setStatus] = useState(null); + const [data, setData] = useState(null); + const timeoutIdRef = useRef | null>(null); + + const [didInitialFetch, setDidInitialFetch] = useState(false); + + useEffect(() => { + setDidInitialFetch(false); + return () => { + // when a connectorId changes, clear timeout + if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current); + }; + }, [connectorId]); + + const handleResponse = useCallback( + (responseData: AttackDiscoveryResponse | null) => { + if (connectorId == null || connectorId === '') { + throw new Error('Invalid connector id'); + } + setDidInitialFetch(true); + if (responseData == null) { + setStatus(null); + setData(null); + return; + } + setData((prevData) => { + if ( + responseData.updatedAt === prevData?.updatedAt && + responseData.status === prevData?.status && + responseData.id === prevData?.id + ) { + // do not update if the data is the same + // prevents unnecessary re-renders + return prevData; + } + setStatus(responseData.status); + setApproximateFutureTime( + moment(responseData.updatedAt) + .add(responseData.averageIntervalMs, 'milliseconds') + .toDate() + ); + return { + ...responseData, + connectorId, + attackDiscoveries: responseData.attackDiscoveries.map((attackDiscovery) => ({ + ...attackDiscovery, + id: attackDiscovery.id ?? uuid.v4(), + detailsMarkdown: replaceNewlineLiterals(attackDiscovery.detailsMarkdown), + entitySummaryMarkdown: replaceNewlineLiterals(attackDiscovery.entitySummaryMarkdown), + summaryMarkdown: replaceNewlineLiterals(attackDiscovery.summaryMarkdown), + })), + }; + }); + }, + [connectorId, setApproximateFutureTime] + ); + + const cancelAttackDiscovery = useCallback(async () => { + try { + if (connectorId == null || connectorId === '') { + throw new Error('Invalid connector id'); + } + if (timeoutIdRef.current) clearTimeout(timeoutIdRef.current); + const rawResponse = await http.fetch( + `/internal/elastic_assistant/attack_discovery/cancel/${connectorId}`, + { + method: 'PUT', + version: ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, + } + ); + const parsedResponse = AttackDiscoveryCancelResponse.safeParse(rawResponse); + if (!parsedResponse.success) { + throw new Error('Failed to parse the attack discovery cancel response'); + } + handleResponse(parsedResponse.data); + } catch (error) { + setStatus(null); + + toasts?.addDanger(error, { + title: ERROR_CANCELING_ATTACK_DISCOVERIES, + text: getErrorToastText(error), + }); + } + }, [connectorId, handleResponse, http, toasts]); + + const pollApi = useCallback(async () => { + try { + if (connectorId == null || connectorId === '') { + throw new Error('Invalid connector id'); + } + // call the internal API to generate attack discoveries: + const rawResponse = await http.fetch( + `/internal/elastic_assistant/attack_discovery/${connectorId}`, + { + method: 'GET', + version: ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, + } + ); + + const parsedResponse = AttackDiscoveryGetResponse.safeParse(rawResponse); + if (!parsedResponse.success) { + throw new Error('Failed to parse the attack discovery GET response'); + } + handleResponse(parsedResponse.data.data ?? null); + if (parsedResponse?.data?.data?.status === attackDiscoveryStatus.running) { + // poll every 3 seconds if attack discovery is running + timeoutIdRef.current = setTimeout(() => { + pollApi(); + }, 3000); + } + } catch (error) { + setStatus(null); + setData(null); + + toasts?.addDanger(error, { + title: ERROR_GENERATING_ATTACK_DISCOVERIES, + text: getErrorToastText(error), + }); + } + }, [connectorId, handleResponse, http, toasts]); + + return { cancelAttackDiscovery, didInitialFetch, status, data, pollApi }; +}; + +export const attackDiscoveryStatus: { [k: string]: AttackDiscoveryStatus } = { + canceled: 'canceled', + failed: 'failed', + running: 'running', + succeeded: 'succeeded', +}; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_use_attack_discovery.ts b/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_use_attack_discovery.ts index e165fb2d83562..617f599e09c8f 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_use_attack_discovery.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_use_attack_discovery.ts @@ -12,365 +12,36 @@ export const getMockUseAttackDiscoveriesWithCachedAttackDiscoveries = ( ): UseAttackDiscovery => ({ alertsContextCount: 20, approximateFutureTime: null, - cachedAttackDiscoveries: { - claudeV3SonnetUsEast1: { - connectorId: 'claudeV3SonnetUsEast1', - attackDiscoveries: [ - { - alertIds: [ - 'e770a817-0e87-4e4b-8e26-1bf504a209d2', - 'f0ab5b5d-55c5-4d05-8f4f-12f0e62ecd96', - '8cfde870-cd3b-40b8-9999-901c0b97fb5a', - 'da8fa0b1-1f51-4c63-b5d0-2e35c9fa3b84', - '597fd583-4036-4631-a71a-7a8a7dd17848', - '550691a2-edac-4cc5-a453-6a36d5351c76', - 'df97c2d9-9e28-43e0-a461-3bacf91a262f', - 'f6558144-630c-49ec-8aa2-fe96364883c7', - '113819ec-cfd0-4867-bfbd-cb9ca8e1e69f', - 'c6cbd80f-9602-4748-b951-56c0745f3e1f', - ], - detailsMarkdown: - '- {{ host.name 001cc415-42ad-4b21-a92c-e4193b283b78 }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }} were involved in a potential ransomware attack progression:\n\n - A suspicious executable {{ file.name d55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e.exe }} was created and executed from {{ file.path 4053a825-9628-470a-8c83-c733e941bece }} by the parent process {{ process.parent.executable C:\\Windows\\Explorer.EXE }}.\n - The suspicious executable then created another file {{ file.name 604300eb-3711-4e38-8500-0a395d3cc1e5 }} at {{ file.path 8e2853aa-f0b9-4c95-9895-d71a7aa8b4a4 }} and loaded it.\n - Multiple shellcode injection alerts were triggered by the loaded file, indicating potential malicious activity.\n - A ransomware detection alert was also triggered, suggesting the presence of ransomware behavior.\n\n- The suspicious executable {{ file.name d55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e.exe }} had an expired code signature from "TRANSPORT", which is not a trusted source.\n- The loaded file {{ file.name 604300eb-3711-4e38-8500-0a395d3cc1e5 }} was identified as potentially malicious by Elastic Endpoint Security.', - entitySummaryMarkdown: - 'Potential ransomware attack involving {{ host.name 001cc415-42ad-4b21-a92c-e4193b283b78 }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }}.', - id: '9f6d4a18-7483-4103-92e7-24e2ebab77bb', - mitreAttackTactics: [ - 'Execution', - 'Persistence', - 'Privilege Escalation', - 'Defense Evasion', - ], - summaryMarkdown: - 'A potential ransomware attack progression was detected on {{ host.name 001cc415-42ad-4b21-a92c-e4193b283b78 }} involving {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }}. A suspicious executable with an untrusted code signature was executed, leading to the creation and loading of a malicious file that triggered shellcode injection and ransomware detection alerts.', - title: 'Potential Ransomware Attack Progression Detected', - }, - { - alertIds: [ - '4691c8da-ccba-40f2-b540-0ec5656ad8ef', - '53b3ee1a-1594-447d-94a0-338af2a22844', - '2e744d88-3040-4ab8-90a3-1d5011ab1a6b', - '452ed87e-2e64-486b-ad6a-b368010f570a', - 'd2ce2be7-1d86-4fbe-851a-05883e575a0b', - '7d0ae0fc-7c24-4760-8543-dc4d44f17126', - ], - detailsMarkdown: - '- {{ host.name 4d31c85a-f08b-4461-a67e-ca1991427e6d }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }} were involved in a potential malware attack progression:\n\n - A Microsoft Office process ({{ process.parent.executable C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE }}) launched a suspicious child process ({{ process.name certutil.exe }}) with unusual arguments to decode a file ({{ file.name B1Z8U2N9.txt }}) into another executable ({{ file.name Q3C7N1V8.exe }}).\n - The decoded executable {{ file.name Q3C7N1V8.exe }} was then executed and created another file {{ file.name 2ddee627-fbe2-45a8-8b2b-eba7542b4e3d }} at {{ file.path ae8aacc8-bfe3-4735-8075-a135fcf60722 }}, which was loaded.\n - Multiple alerts were triggered, including malware detection, suspicious Microsoft Office child process, uncommon persistence via registry modification, and rundll32 with unusual arguments.\n\n- The decoded executable {{ file.name Q3C7N1V8.exe }} exhibited persistence behavior by modifying the registry.\n- The rundll32.exe process was launched with unusual arguments to load the decoded file, which is a common malware technique.', - entitySummaryMarkdown: - 'Potential malware attack involving {{ host.name 4d31c85a-f08b-4461-a67e-ca1991427e6d }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }}.', - id: 'fd82a3bf-45e4-43ba-bb8f-795584923474', - mitreAttackTactics: ['Execution', 'Persistence', 'Defense Evasion'], - summaryMarkdown: - 'A potential malware attack progression was detected on {{ host.name 4d31c85a-f08b-4461-a67e-ca1991427e6d }} involving {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }}. A Microsoft Office process launched a suspicious child process that decoded and executed a malicious executable, which exhibited persistence behavior and triggered multiple security alerts.', - title: 'Potential Malware Attack Progression Detected', - }, - { - alertIds: ['9896f807-4e57-4da8-b1ea-d62645045428'], - detailsMarkdown: - '- {{ host.name c7697774-7350-4153-9061-64a484500241 }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }} were involved in a potential malware attack:\n\n - A Microsoft Office process ({{ process.parent.executable C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE }}) launched a suspicious child process ({{ process.name certutil.exe }}) with unusual arguments to decode a file ({{ file.name K2G8Q8Z9.txt }}) into another executable ({{ file.name Z5K7J6H8.exe }}).\n - This behavior triggered a "Malicious Behavior Prevention Alert: Suspicious Microsoft Office Child Process" alert.\n\n- The certutil.exe process is commonly abused by malware to decode and execute malicious payloads.', - entitySummaryMarkdown: - 'Potential malware attack involving {{ host.name c7697774-7350-4153-9061-64a484500241 }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }}.', - id: '79a97cec-4126-479a-8fa1-706aec736bc5', - mitreAttackTactics: ['Execution', 'Defense Evasion'], - summaryMarkdown: - 'A potential malware attack was detected on {{ host.name c7697774-7350-4153-9061-64a484500241 }} involving {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }}. A Microsoft Office process launched a suspicious child process that attempted to decode and execute a malicious payload, triggering a security alert.', - title: 'Potential Malware Attack Detected', - }, - { - alertIds: ['53157916-4437-4a92-a7fd-f792c4aa1aae'], - detailsMarkdown: - '- {{ host.name 6d4355b3-3d1a-4673-b0c7-51c1c698bcc5 }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }} were involved in a potential malware incident:\n\n - The explorer.exe process ({{ process.executable C:\\Windows\\explorer.exe }}) attempted to create a file ({{ file.name 25a994dc-c605-425c-b139-c273001dc816 }}) at {{ file.path 9693f967-2b96-4281-893e-79adbdcf1066 }}.\n - This file creation attempt was blocked, and a "Malware Prevention Alert" was triggered.\n\n- The file {{ file.name 25a994dc-c605-425c-b139-c273001dc816 }} was likely identified as malicious by Elastic Endpoint Security, leading to the prevention of its creation.', - entitySummaryMarkdown: - 'Potential malware incident involving {{ host.name 6d4355b3-3d1a-4673-b0c7-51c1c698bcc5 }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }}.', - id: '13c4a00d-88a8-408c-9ed5-b2518df0eae3', - mitreAttackTactics: ['Defense Evasion'], - summaryMarkdown: - 'A potential malware incident was detected on {{ host.name 6d4355b3-3d1a-4673-b0c7-51c1c698bcc5 }} involving {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }}. The explorer.exe process attempted to create a file that was identified as malicious by Elastic Endpoint Security, triggering a malware prevention alert and blocking the file creation.', - title: 'Potential Malware Incident Detected', - }, - ], - replacements: { - '8e2853aa-f0b9-4c95-9895-d71a7aa8b4a4': 'C:\\Windows\\mpsvc.dll', - '73f9a91c-3268-4229-8bb9-7c1fe2f667bc': 'Administrator', - '001cc415-42ad-4b21-a92c-e4193b283b78': 'SRVWIN02', - 'b0fd402c-9752-4d43-b0f7-9750cce247e7': 'OMM-WIN-DETECT', - '604300eb-3711-4e38-8500-0a395d3cc1e5': 'mpsvc.dll', - 'e770a817-0e87-4e4b-8e26-1bf504a209d2': - '13c8569b2bfd65ecfa75b264b6d7f31a1b50c530101bcaeb8569b3a0190e93b4', - 'f0ab5b5d-55c5-4d05-8f4f-12f0e62ecd96': - '250d812f9623d0916bba521d4221757163f199d64ffab92f888581a00ca499be', - '4053a825-9628-470a-8c83-c733e941bece': - 'C:\\Users\\Administrator\\Desktop\\8813719803\\d55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e.exe', - '2acbc31d-a0ec-4f99-a544-b23fcdd37b70': - 'd55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e.exe', - '8cfde870-cd3b-40b8-9999-901c0b97fb5a': - '138876c616a2f403aadb6a1c3da316d97f15669fc90187a27d7f94a55674d19a', - 'da8fa0b1-1f51-4c63-b5d0-2e35c9fa3b84': - '2bc20691da4ec37cc1f967d6f5b79e95c7f07f6e473724479dcf4402a192969c', - '9693f967-2b96-4281-893e-79adbdcf1066': - 'C:\\Users\\Administrator\\Desktop\\8813719803\\d55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e', - '25a994dc-c605-425c-b139-c273001dc816': - 'd55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e', - '597fd583-4036-4631-a71a-7a8a7dd17848': - '6cea6124aa27adf2f782db267c5173742b675331107cdb7372a46ae469366210', - '550691a2-edac-4cc5-a453-6a36d5351c76': - '26a9788ca7189baa31dcbb509779c1ac5d2e72297cb02e4b4ee8c1f9e371666f', - 'df97c2d9-9e28-43e0-a461-3bacf91a262f': - 'c107e4e903724f2a1e0ea8e0135032d1d75624bf7de8b99c17ba9a9f178c2d6a', - 'f6558144-630c-49ec-8aa2-fe96364883c7': - 'afb8ed160ae9f78990980d92fb3213ffff74a12ec75034384b4f53a3edf74400', - 'c6cbd80f-9602-4748-b951-56c0745f3e1f': - '137aa729928d2a0df1d5e35f47f0ad2bd525012409a889358476dca8e06ba804', - '113819ec-cfd0-4867-bfbd-cb9ca8e1e69f': - '5bec676e7faa4b6329027c9798e70e6d5e7a4d6d08696597dc8a3b31490bdfe5', - 'ae8aacc8-bfe3-4735-8075-a135fcf60722': - 'C:\\Users\\Administrator\\AppData\\Local\\cdnver.dll', - '4d31c85a-f08b-4461-a67e-ca1991427e6d': 'SRVWIN01', - '2ddee627-fbe2-45a8-8b2b-eba7542b4e3d': 'cdnver.dll', - '8e8e2e05-521d-4988-b7ce-4763fea1faf0': - 'f5d9e2d82dad1ff40161b92c097340ee07ae43715f6c9270705fb0db7a9eeca4', - '4691c8da-ccba-40f2-b540-0ec5656ad8ef': - 'b4bf1d7b993141f813008dccab0182af3c810de0c10e43a92ac0d9d5f1dbf42e', - '53b3ee1a-1594-447d-94a0-338af2a22844': - '4ab871ec3d41d3271c2a1fc3861fabcbc06f7f4534a1b6f741816417bc73927c', - '2e744d88-3040-4ab8-90a3-1d5011ab1a6b': - '1f492a1b66f6c633a81a4c6318345b07f6d05624714da0b0cb7dd6d8e374e249', - '9e44ac92-1d88-4cfc-9f38-781c3457b395': - 'e6fba60799acc5bf85ca34ec634482b95ac941c71e9822dfa34d9d774dd1e2bd', - '5164c2f3-9f96-4867-a263-cc7041b06ece': 'C:\\ProgramData\\Q3C7N1V8.exe', - '0aaff15a-a311-46b8-b20b-0db550e5005e': 'Q3C7N1V8.exe', - '452ed87e-2e64-486b-ad6a-b368010f570a': - '4be1be7b4351f2e94fa706ea1ab7f9dd7c3267a77832e94794ebb2b0a6d8493a', - '84e2000b-3c0a-4775-9903-89ebe953f247': 'C:\\Programdata\\Q3C7N1V8.exe', - 'd2ce2be7-1d86-4fbe-851a-05883e575a0b': - '5ed1aa94157bd6b949bf1527320caf0e6f5f61d86518e5f13912314d0f024e88', - '7d0ae0fc-7c24-4760-8543-dc4d44f17126': - 'a786f965902ed5490656f48adc79b46676dc2518a052759625f6108bbe2d864d', - 'c7697774-7350-4153-9061-64a484500241': 'SRVWIN01-PRIV', - 'b26da819-a141-4efd-84b0-6d2876f8800d': 'OMM-WIN-PREVENT', - '9896f807-4e57-4da8-b1ea-d62645045428': - '2a33e2c6150dfc6f0d49022fc0b5aefc90db76b6e237371992ebdee909d3c194', - '6d4355b3-3d1a-4673-b0c7-51c1c698bcc5': 'SRVWIN02-PRIV', - '53157916-4437-4a92-a7fd-f792c4aa1aae': - '605ebf550ae0ffc4aec2088b97cbf99853113b0db81879500547c4277ca1981a', - }, - updated: new Date('2024-04-15T13:48:44.393Z'), + isLoadingPost: false, + didInitialFetch: true, + failureReason: null, + generationIntervals: [ + { + date: new Date('2024-04-15T13:48:44.397Z').toISOString(), + durationMs: 85807, }, - claudeV3SonnetUsWest2: { - connectorId: 'claudeV3SonnetUsWest2', - attackDiscoveries: [ - { - alertIds: [ - 'e6b49cac-a5d0-4d22-a7e2-868881aa9d20', - '648d8ad4-6f4e-4c06-99f7-cdbce20f4480', - 'bbfc0fd4-fbad-4ac4-b1b4-a9acd91ac504', - 'c1252ff5-113a-4fe8-b341-9726c5011402', - 'a3544119-12a0-4dd2-97b8-ed211233393b', - '3575d826-2350-4a4d-bb26-c92c324f38ca', - '778fd5cf-13b9-40fe-863d-abac2a6fe3c7', - '2ed82499-db91-4197-ad8d-5f03f59c6616', - '280e1e76-3a10-470c-8adc-094094badb1d', - '61ae312a-82c7-4bae-8014-f3790628b82f', - ], - detailsMarkdown: - '- {{ host.name fb5608fd-5bf4-4b28-8ea8-a51160df847f }} was compromised by a malicious executable {{ file.name d55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e.exe }} launched from {{ process.parent.executable C:\\Windows\\Explorer.EXE }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}\n\n- The malicious executable created a suspicious file {{ file.name d2aeb0e2-e327-4979-aa31-d46454d5b1a5 }} and loaded it into memory via {{ process.executable C:\\Windows\\MsMpEng.exe }}\n\n- This behavior triggered multiple alerts for shellcode injection, ransomware activity, and other malicious behaviors\n\n- The malware appears to be a variant of ransomware', - entitySummaryMarkdown: - 'Malicious activity detected on {{ host.name fb5608fd-5bf4-4b28-8ea8-a51160df847f }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}', - id: 'e536ae7a-4ae8-4e47-9f20-0e40ac675d56', - mitreAttackTactics: [ - 'Initial Access', - 'Execution', - 'Persistence', - 'Privilege Escalation', - 'Defense Evasion', - 'Discovery', - 'Lateral Movement', - 'Collection', - 'Exfiltration', - 'Impact', - ], - summaryMarkdown: - 'Multiple critical alerts indicate a ransomware attack on {{ host.name fb5608fd-5bf4-4b28-8ea8-a51160df847f }}, likely initiated by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}', - title: 'Ransomware Attack', - }, - { - alertIds: [ - 'b544dd2a-e208-4dac-afba-b60f799ab623', - '7d3a4bae-3bd7-41a7-aee2-f68088aef1d5', - 'd1716ee3-e12e-4b03-8057-b9320f3ce825', - 'ca31a2b6-cb77-4ca2-ada0-14bb39ec1a2e', - 'a0b56cd3-1f7f-4221-bc88-6efb4082e781', - '2ab6a581-e2ab-4a54-a0e1-7b23bf8299cb', - '1d1040c3-9e30-47fb-b2cf-f9e8ab647547', - ], - detailsMarkdown: - '- {{ host.name b6fb7e37-e3d6-47aa-b176-83d800984be8 }} was compromised by a malicious executable {{ file.name 94b3c78d-c647-4ee1-9eba-8101b806a7af }} launched from {{ process.parent.executable C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}\n\n- The malicious executable was decoded from a file {{ file.name 30820807-30f3-4b43-bb1d-c523d6375f49 }} using certutil.exe, which is a common malware technique\n\n- It established persistence by modifying registry keys and loading a malicious DLL {{ file.name 30820807-30f3-4b43-bb1d-c523d6375f49 }} via rundll32.exe\n\n- This behavior triggered alerts for malware, suspicious Microsoft Office child processes, and uncommon persistence mechanisms', - entitySummaryMarkdown: - 'Malicious activity detected on {{ host.name b6fb7e37-e3d6-47aa-b176-83d800984be8 }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}', - id: '36d3daf0-93f0-4887-8d2c-a935863091a0', - mitreAttackTactics: [ - 'Initial Access', - 'Execution', - 'Persistence', - 'Privilege Escalation', - 'Defense Evasion', - 'Discovery', - ], - summaryMarkdown: - 'Multiple critical alerts indicate a malware infection on {{ host.name b6fb7e37-e3d6-47aa-b176-83d800984be8 }} likely initiated by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }} via a malicious Microsoft Office document', - title: 'Malware Infection via Malicious Office Document', - }, - { - alertIds: ['67a27f31-f18f-4256-b64f-63e718eb688e'], - detailsMarkdown: - '- {{ host.name b8639719-38c4-401e-8582-6e8ea098feef }} was targeted by a malicious executable that attempted to be decoded from a file using certutil.exe, which is a common malware technique\n\n- The malicious activity was initiated from {{ process.parent.executable C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}, likely via a malicious Microsoft Office document\n\n- This behavior triggered an alert for a suspicious Microsoft Office child process', - entitySummaryMarkdown: - 'Suspected malicious activity detected on {{ host.name b8639719-38c4-401e-8582-6e8ea098feef }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}', - id: 'bbf6f5fc-f739-4598-945b-463dea90ea50', - mitreAttackTactics: ['Initial Access', 'Execution', 'Defense Evasion'], - summaryMarkdown: - 'A suspicious Microsoft Office child process was detected on {{ host.name b8639719-38c4-401e-8582-6e8ea098feef }}, potentially initiated by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }} via a malicious document', - title: 'Suspected Malicious Activity via Office Document', - }, - { - alertIds: ['2242a749-7d59-4f24-8b33-b8772ab4f8df'], - detailsMarkdown: - '- A suspicious file creation attempt {{ file.name efcf53ac-3943-4d7d-96b5-d84eefd2c478 }} with the same hash as a known malicious executable was blocked on {{ host.name 6bcc5c79-2171-4c71-9bea-fe0c116d3803 }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}\n\n- The file was likely being staged for later malicious activity\n\n- This triggered a malware prevention alert, indicating the threat was detected and mitigated', - entitySummaryMarkdown: - 'Suspected malicious file blocked on {{ host.name 6bcc5c79-2171-4c71-9bea-fe0c116d3803 }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}', - id: '069a5b43-1458-4e87-8dc6-97459a020ef8', - mitreAttackTactics: ['Initial Access', 'Execution'], - summaryMarkdown: - 'A suspected malicious file creation was blocked on {{ host.name 6bcc5c79-2171-4c71-9bea-fe0c116d3803 }} by {{ user.name 4f7ff689-3079-4811-8fec-8c2bc2646cc2 }}', - title: 'Suspected Malicious File Creation Blocked', - }, - ], - replacements: { - '6fcdf365-367a-4695-b08e-519c31345fec': 'C:\\Windows\\mpsvc.dll', - '4f7ff689-3079-4811-8fec-8c2bc2646cc2': 'Administrator', - 'fb5608fd-5bf4-4b28-8ea8-a51160df847f': 'SRVWIN02', - 'a141c5f0-5c06-41b8-8399-27c03a459398': 'OMM-WIN-DETECT', - 'd2aeb0e2-e327-4979-aa31-d46454d5b1a5': 'mpsvc.dll', - 'e6b49cac-a5d0-4d22-a7e2-868881aa9d20': - '13c8569b2bfd65ecfa75b264b6d7f31a1b50c530101bcaeb8569b3a0190e93b4', - '648d8ad4-6f4e-4c06-99f7-cdbce20f4480': - '250d812f9623d0916bba521d4221757163f199d64ffab92f888581a00ca499be', - 'fca45966-448c-4652-9e02-2600dfa02a35': - 'C:\\Users\\Administrator\\Desktop\\8813719803\\d55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e.exe', - '5b9f846a-c497-4631-8a2f-7de265bfc864': - 'd55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e.exe', - 'bbfc0fd4-fbad-4ac4-b1b4-a9acd91ac504': - '138876c616a2f403aadb6a1c3da316d97f15669fc90187a27d7f94a55674d19a', - '61ae312a-82c7-4bae-8014-f3790628b82f': - '2bc20691da4ec37cc1f967d6f5b79e95c7f07f6e473724479dcf4402a192969c', - 'f1bbf0b8-d417-438f-ad09-dd8a854e0abb': - 'C:\\Users\\Administrator\\Desktop\\8813719803\\d55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e', - 'efcf53ac-3943-4d7d-96b5-d84eefd2c478': - 'd55f983c994caa160ec63a59f6b4250fe67fb3e8c43a388aec60a4a6978e9f1e', - 'c1252ff5-113a-4fe8-b341-9726c5011402': - '6cea6124aa27adf2f782db267c5173742b675331107cdb7372a46ae469366210', - 'a3544119-12a0-4dd2-97b8-ed211233393b': - '26a9788ca7189baa31dcbb509779c1ac5d2e72297cb02e4b4ee8c1f9e371666f', - '3575d826-2350-4a4d-bb26-c92c324f38ca': - 'c107e4e903724f2a1e0ea8e0135032d1d75624bf7de8b99c17ba9a9f178c2d6a', - '778fd5cf-13b9-40fe-863d-abac2a6fe3c7': - 'afb8ed160ae9f78990980d92fb3213ffff74a12ec75034384b4f53a3edf74400', - '2ed82499-db91-4197-ad8d-5f03f59c6616': - '137aa729928d2a0df1d5e35f47f0ad2bd525012409a889358476dca8e06ba804', - '280e1e76-3a10-470c-8adc-094094badb1d': - '5bec676e7faa4b6329027c9798e70e6d5e7a4d6d08696597dc8a3b31490bdfe5', - '6fad79d9-1ed4-4c1d-8b30-43023b7a5552': - 'C:\\Users\\Administrator\\AppData\\Local\\cdnver.dll', - 'b6fb7e37-e3d6-47aa-b176-83d800984be8': 'SRVWIN01', - '30820807-30f3-4b43-bb1d-c523d6375f49': 'cdnver.dll', - '1d1040c3-9e30-47fb-b2cf-f9e8ab647547': - 'f5d9e2d82dad1ff40161b92c097340ee07ae43715f6c9270705fb0db7a9eeca4', - 'b544dd2a-e208-4dac-afba-b60f799ab623': - 'b4bf1d7b993141f813008dccab0182af3c810de0c10e43a92ac0d9d5f1dbf42e', - '7d3a4bae-3bd7-41a7-aee2-f68088aef1d5': - '4ab871ec3d41d3271c2a1fc3861fabcbc06f7f4534a1b6f741816417bc73927c', - 'd1716ee3-e12e-4b03-8057-b9320f3ce825': - '1f492a1b66f6c633a81a4c6318345b07f6d05624714da0b0cb7dd6d8e374e249', - 'ca31a2b6-cb77-4ca2-ada0-14bb39ec1a2e': - 'e6fba60799acc5bf85ca34ec634482b95ac941c71e9822dfa34d9d774dd1e2bd', - '03bcdffb-54d1-457e-9599-f10b93e10ed3': 'C:\\ProgramData\\Q3C7N1V8.exe', - '94b3c78d-c647-4ee1-9eba-8101b806a7af': 'Q3C7N1V8.exe', - '8fd14f7c-6b89-43b2-b58e-09502a007e21': - '4be1be7b4351f2e94fa706ea1ab7f9dd7c3267a77832e94794ebb2b0a6d8493a', - '2342b541-1c6b-4d59-bbd4-d897637573e1': 'C:\\Programdata\\Q3C7N1V8.exe', - 'a0b56cd3-1f7f-4221-bc88-6efb4082e781': - '5ed1aa94157bd6b949bf1527320caf0e6f5f61d86518e5f13912314d0f024e88', - '2ab6a581-e2ab-4a54-a0e1-7b23bf8299cb': - 'a786f965902ed5490656f48adc79b46676dc2518a052759625f6108bbe2d864d', - 'b8639719-38c4-401e-8582-6e8ea098feef': 'SRVWIN01-PRIV', - '0549244b-3878-4ff8-a327-1758b8e88c10': 'OMM-WIN-PREVENT', - '67a27f31-f18f-4256-b64f-63e718eb688e': - '2a33e2c6150dfc6f0d49022fc0b5aefc90db76b6e237371992ebdee909d3c194', - '6bcc5c79-2171-4c71-9bea-fe0c116d3803': 'SRVWIN02-PRIV', - '2242a749-7d59-4f24-8b33-b8772ab4f8df': - '605ebf550ae0ffc4aec2088b97cbf99853113b0db81879500547c4277ca1981a', - }, - updated: new Date('2024-04-15T15:11:24.903Z'), + { + date: new Date('2024-04-15T12:41:15.255Z').toISOString(), + durationMs: 12751, }, - }, - generationIntervals: { - claudeV3SonnetUsEast1: [ - { - connectorId: 'claudeV3SonnetUsEast1', - date: new Date('2024-04-15T13:48:44.397Z'), - durationMs: 85807, - }, - { - connectorId: 'claudeV3SonnetUsEast1', - date: new Date('2024-04-15T12:41:15.255Z'), - durationMs: 12751, - }, - { - connectorId: 'claudeV3SonnetUsEast1', - date: new Date('2024-04-12T20:59:13.238Z'), - durationMs: 46169, - }, - { - connectorId: 'claudeV3SonnetUsEast1', - date: new Date('2024-04-12T19:34:56.701Z'), - durationMs: 86674, - }, - { - connectorId: 'claudeV3SonnetUsEast1', - date: new Date('2024-04-12T19:17:21.697Z'), - durationMs: 78486, - }, - ], - claudeV3SonnetUsWest2: [ - { - connectorId: 'claudeV3SonnetUsWest2', - date: new Date('2024-04-15T15:11:24.906Z'), - durationMs: 71715, - }, - { - connectorId: 'claudeV3SonnetUsWest2', - date: new Date('2024-04-12T13:13:35.335Z'), - durationMs: 66176, - }, - { - connectorId: 'claudeV3SonnetUsWest2', - date: new Date('2024-04-11T18:30:36.360Z'), - durationMs: 88079, - }, - { - connectorId: 'claudeV3SonnetUsWest2', - date: new Date('2024-04-11T18:12:50.350Z'), - durationMs: 77704, - }, - { - connectorId: 'claudeV3SonnetUsWest2', - date: new Date('2024-04-11T17:57:21.902Z'), - durationMs: 77016, - }, - ], - }, + { + date: new Date('2024-04-12T20:59:13.238Z').toISOString(), + durationMs: 46169, + }, + { + date: new Date('2024-04-12T19:34:56.701Z').toISOString(), + durationMs: 86674, + }, + { + date: new Date('2024-04-12T19:17:21.697Z').toISOString(), + durationMs: 78486, + }, + ], fetchAttackDiscoveries, + onCancel: jest.fn(), attackDiscoveries: [ { + timestamp: new Date('2024-04-15T15:11:24.906Z').toISOString(), alertIds: [ 'e770a817-0e87-4e4b-8e26-1bf504a209d2', 'f0ab5b5d-55c5-4d05-8f4f-12f0e62ecd96', @@ -394,6 +65,7 @@ export const getMockUseAttackDiscoveriesWithCachedAttackDiscoveries = ( title: 'Potential Ransomware Attack Progression Detected', }, { + timestamp: new Date('2024-04-15T15:11:24.906Z').toISOString(), alertIds: [ '4691c8da-ccba-40f2-b540-0ec5656ad8ef', '53b3ee1a-1594-447d-94a0-338af2a22844', @@ -413,6 +85,7 @@ export const getMockUseAttackDiscoveriesWithCachedAttackDiscoveries = ( title: 'Potential Malware Attack Progression Detected', }, { + timestamp: new Date('2024-04-15T15:11:24.906Z').toISOString(), alertIds: ['9896f807-4e57-4da8-b1ea-d62645045428'], detailsMarkdown: '- {{ host.name c7697774-7350-4153-9061-64a484500241 }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }} were involved in a potential malware attack:\n\n - A Microsoft Office process ({{ process.parent.executable C:\\Program Files\\Microsoft Office\\root\\Office16\\EXCEL.EXE }}) launched a suspicious child process ({{ process.name certutil.exe }}) with unusual arguments to decode a file ({{ file.name K2G8Q8Z9.txt }}) into another executable ({{ file.name Z5K7J6H8.exe }}).\n - This behavior triggered a "Malicious Behavior Prevention Alert: Suspicious Microsoft Office Child Process" alert.\n\n- The certutil.exe process is commonly abused by malware to decode and execute malicious payloads.', @@ -425,6 +98,7 @@ export const getMockUseAttackDiscoveriesWithCachedAttackDiscoveries = ( title: 'Potential Malware Attack Detected', }, { + timestamp: new Date('2024-04-15T15:11:24.906Z').toISOString(), alertIds: ['53157916-4437-4a92-a7fd-f792c4aa1aae'], detailsMarkdown: '- {{ host.name 6d4355b3-3d1a-4673-b0c7-51c1c698bcc5 }} and {{ user.name 73f9a91c-3268-4229-8bb9-7c1fe2f667bc }} were involved in a potential malware incident:\n\n - The explorer.exe process ({{ process.executable C:\\Windows\\explorer.exe }}) attempted to create a file ({{ file.name 25a994dc-c605-425c-b139-c273001dc816 }}) at {{ file.path 9693f967-2b96-4281-893e-79adbdcf1066 }}.\n - This file creation attempt was blocked, and a "Malware Prevention Alert" was triggered.\n\n- The file {{ file.name 25a994dc-c605-425c-b139-c273001dc816 }} was likely identified as malicious by Elastic Endpoint Security, leading to the prevention of its creation.', @@ -505,29 +179,18 @@ export const getMockUseAttackDiscoveriesWithCachedAttackDiscoveries = ( isLoading: false, }); -export const getMockUseAttackDiscoveriesWithNoAttackDiscoveries = ( - fetchAttackDiscoveries: () => Promise -): UseAttackDiscovery => ({ - alertsContextCount: null, - approximateFutureTime: null, - cachedAttackDiscoveries: {}, - fetchAttackDiscoveries, - generationIntervals: undefined, - attackDiscoveries: [], - lastUpdated: null, - replacements: {}, - isLoading: false, -}); - export const getMockUseAttackDiscoveriesWithNoAttackDiscoveriesLoading = ( fetchAttackDiscoveries: () => Promise ): UseAttackDiscovery => ({ alertsContextCount: null, approximateFutureTime: new Date('2024-04-15T17:13:29.470Z'), // <-- estimated generation completion time - cachedAttackDiscoveries: {}, fetchAttackDiscoveries, + onCancel: jest.fn(), generationIntervals: undefined, attackDiscoveries: [], + isLoadingPost: false, + didInitialFetch: true, + failureReason: null, lastUpdated: null, replacements: {}, isLoading: true, // <-- attack discoveries are being generated diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_states/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_states/index.test.tsx index 406b9a4233d7c..460511defbdf9 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_states/index.test.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_states/index.test.tsx @@ -32,6 +32,7 @@ describe('EmptyStates', () => { alertsCount={alertsCount} attackDiscoveriesCount={attackDiscoveriesCount} connectorId={connectorId} + failureReason={null} isLoading={isLoading} onGenerate={onGenerate} /> @@ -72,6 +73,7 @@ describe('EmptyStates', () => { alertsCount={alertsCount} attackDiscoveriesCount={attackDiscoveriesCount} connectorId={connectorId} + failureReason={null} isLoading={isLoading} onGenerate={onGenerate} /> @@ -83,6 +85,10 @@ describe('EmptyStates', () => { expect(screen.queryByTestId('welcome')).not.toBeInTheDocument(); }); + it('does NOT render the Failure prompt', () => { + expect(screen.queryByTestId('failure')).not.toBeInTheDocument(); + }); + it('renders the No Alerts prompt', () => { expect(screen.getByTestId('noAlerts')).toBeInTheDocument(); }); @@ -92,6 +98,51 @@ describe('EmptyStates', () => { }); }); + describe('when the Failure prompt should be shown', () => { + beforeEach(() => { + jest.clearAllMocks(); + + const aiConnectorsCount = 1; + const alertsContextCount = 10; + const alertsCount = 10; + const attackDiscoveriesCount = 10; + const connectorId = 'test-connector-id'; + const isLoading = false; + const onGenerate = jest.fn(); + + render( + + + + ); + }); + + it('does NOT render the Welcome prompt', () => { + expect(screen.queryByTestId('welcome')).not.toBeInTheDocument(); + }); + + it('renders the Failure prompt', () => { + expect(screen.getByTestId('failure')).toBeInTheDocument(); + }); + + it('does NOT render the No Alerts prompt', () => { + expect(screen.queryByTestId('noAlerts')).not.toBeInTheDocument(); + }); + + it('does NOT render the Empty prompt', () => { + expect(screen.queryByTestId('emptyPrompt')).not.toBeInTheDocument(); + }); + }); + describe('when the Empty prompt should be shown', () => { beforeEach(() => { jest.clearAllMocks(); @@ -112,6 +163,7 @@ describe('EmptyStates', () => { alertsCount={alertsCount} attackDiscoveriesCount={attackDiscoveriesCount} connectorId={connectorId} + failureReason={null} isLoading={isLoading} onGenerate={onGenerate} /> @@ -123,6 +175,10 @@ describe('EmptyStates', () => { expect(screen.queryByTestId('welcome')).not.toBeInTheDocument(); }); + it('does NOT render the Failure prompt', () => { + expect(screen.queryByTestId('failure')).not.toBeInTheDocument(); + }); + it('does NOT render the No Alerts prompt', () => { expect(screen.queryByTestId('noAlerts')).not.toBeInTheDocument(); }); @@ -154,6 +210,7 @@ describe('EmptyStates', () => { alertsCount={alertsCount} attackDiscoveriesCount={attackDiscoveriesCount} connectorId={connectorId} + failureReason={null} isLoading={isLoading} onGenerate={onGenerate} /> @@ -165,6 +222,10 @@ describe('EmptyStates', () => { expect(screen.queryByTestId('welcome')).not.toBeInTheDocument(); }); + it('does NOT render the Failure prompt', () => { + expect(screen.queryByTestId('failure')).not.toBeInTheDocument(); + }); + it('does NOT render the No Alerts prompt', () => { expect(screen.queryByTestId('noAlerts')).not.toBeInTheDocument(); }); @@ -200,6 +261,7 @@ describe('EmptyStates', () => { alertsCount={alertsCount} attackDiscoveriesCount={attackDiscoveriesCount} connectorId={connectorId} + failureReason={null} isLoading={isLoading} onGenerate={onGenerate} /> @@ -211,6 +273,10 @@ describe('EmptyStates', () => { expect(screen.queryByTestId('welcome')).not.toBeInTheDocument(); }); + it('does NOT render the Failure prompt', () => { + expect(screen.queryByTestId('failure')).not.toBeInTheDocument(); + }); + it('does NOT render the No Alerts prompt', () => { expect(screen.queryByTestId('noAlerts')).not.toBeInTheDocument(); }); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_states/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_states/index.tsx index 009db0eb6e326..d38200a4be205 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_states/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_states/index.tsx @@ -7,6 +7,7 @@ import React from 'react'; +import { Failure } from '../failure'; import { EmptyPrompt } from '../empty_prompt'; import { showEmptyPrompt, showNoAlertsPrompt, showWelcomePrompt } from '../helpers'; import { NoAlerts } from '../no_alerts'; @@ -18,6 +19,7 @@ interface Props { alertsCount: number; attackDiscoveriesCount: number; connectorId: string | undefined; + failureReason: string | null; isLoading: boolean; onGenerate: () => Promise; } @@ -28,11 +30,14 @@ const EmptyStatesComponent: React.FC = ({ alertsCount, attackDiscoveriesCount, connectorId, + failureReason, isLoading, onGenerate, }) => { if (showWelcomePrompt({ aiConnectorsCount, isLoading })) { return ; + } else if (failureReason !== null) { + return ; } else if (showNoAlertsPrompt({ alertsContextCount, isLoading })) { return ; } else if (showEmptyPrompt({ attackDiscoveriesCount, isLoading })) { diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/index.test.tsx new file mode 100644 index 0000000000000..74778cb49164f --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/index.test.tsx @@ -0,0 +1,53 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Failure } from '.'; +import { LEARN_MORE, FAILURE_TITLE } from './translations'; +const failureReason = "You're a failure"; +describe('Failure', () => { + beforeEach(() => { + render(); + }); + + it('renders the expected title', () => { + const title = screen.getByTestId('failureTitle'); + + expect(title).toHaveTextContent(FAILURE_TITLE); + }); + + it('renders the expected body text', () => { + const bodyText = screen.getByTestId('bodyText'); + + expect(bodyText).toHaveTextContent(failureReason); + }); + + describe('link', () => { + let learnMoreLink: HTMLElement; + + beforeEach(() => { + learnMoreLink = screen.getByTestId('learnMoreLink'); + }); + + it('links to the documentation', () => { + expect(learnMoreLink).toHaveAttribute( + 'href', + 'https://www.elastic.co/guide/en/security/current/attack-discovery.html' + ); + }); + + it('opens in a new tab', () => { + expect(learnMoreLink).toHaveAttribute('target', '_blank'); + }); + + it('has the expected text', () => { + expect(learnMoreLink).toHaveTextContent(LEARN_MORE); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/index.tsx new file mode 100644 index 0000000000000..8de3e0e380c07 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/index.tsx @@ -0,0 +1,43 @@ +/* + * 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 { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiLink, EuiText } from '@elastic/eui'; +import React from 'react'; + +import * as i18n from './translations'; + +const FailureComponent: React.FC<{ failureReason: string }> = ({ failureReason }) => { + return ( + + + + {failureReason} + + } + title={

{i18n.FAILURE_TITLE}

} + /> +
+ + + + {i18n.LEARN_MORE} + + +
+ ); +}; + +export const Failure = React.memo(FailureComponent); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/translations.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/translations.ts new file mode 100644 index 0000000000000..b36104d202ba8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/failure/translations.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 { i18n } from '@kbn/i18n'; + +export const LEARN_MORE = i18n.translate( + 'xpack.securitySolution.attackDiscovery.pages.failure.learnMoreLink', + { + defaultMessage: 'Learn more about Attack discovery', + } +); + +export const FAILURE_TITLE = i18n.translate( + 'xpack.securitySolution.attackDiscovery.pages.failure.title', + { + defaultMessage: 'Attack discovery generation failed', + } +); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/header/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/header/index.tsx index 650eff33fbd93..e62128d3973cf 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/header/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/header/index.tsx @@ -5,11 +5,12 @@ * 2.0. */ +import type { EuiButtonProps } from '@elastic/eui'; import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiToolTip, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import { ConnectorSelectorInline } from '@kbn/elastic-assistant'; import { noop } from 'lodash/fp'; -import React from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useAssistantAvailability } from '../../../assistant/use_assistant_availability'; import * as i18n from './translations'; @@ -18,7 +19,9 @@ interface Props { connectorId: string | undefined; connectorsAreConfigured: boolean; isLoading: boolean; + isDisabledActions: boolean; onGenerate: () => void; + onCancel: () => void; onConnectorIdSelected: (connectorId: string) => void; } @@ -26,13 +29,44 @@ const HeaderComponent: React.FC = ({ connectorId, connectorsAreConfigured, isLoading, + isDisabledActions, onGenerate, onConnectorIdSelected, + onCancel, }) => { const isFlyoutMode = false; // always false for attack discovery const { hasAssistantPrivilege } = useAssistantAvailability(); const { euiTheme } = useEuiTheme(); - const disabled = !hasAssistantPrivilege || isLoading || connectorId == null; + const disabled = !hasAssistantPrivilege || connectorId == null; + + const [didCancel, setDidCancel] = useState(false); + + const handleCancel = useCallback(() => { + setDidCancel(true); + onCancel(); + }, [onCancel]); + + useEffect(() => { + if (isLoading === false) setDidCancel(false); + }, [isLoading]); + + const buttonProps = useMemo( + () => + isLoading + ? { + dataTestSubj: 'cancel', + color: 'danger' as EuiButtonProps['color'], + onClick: handleCancel, + text: i18n.CANCEL, + } + : { + dataTestSubj: 'generate', + color: 'primary' as EuiButtonProps['color'], + onClick: onGenerate, + text: i18n.GENERATE, + }, + [isLoading, handleCancel, onGenerate] + ); return ( = ({ data-test-subj="generateTooltip" > - {isLoading ? i18n.LOADING : i18n.GENERATE} + {buttonProps.text} diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/header/translations.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/header/translations.ts index f155dda9e234f..97c43dfb173de 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/header/translations.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/header/translations.ts @@ -14,10 +14,10 @@ export const GENERATE = i18n.translate( } ); -export const LOADING = i18n.translate( - 'xpack.securitySolution.attackDiscovery.pages.header.loadingButton', +export const CANCEL = i18n.translate( + 'xpack.securitySolution.attackDiscovery.pages.header.cancelButton', { - defaultMessage: 'Loading...', + defaultMessage: 'Cancel', } ); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/index.test.tsx index 0777406ba66f7..ff4e420e0e360 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/index.test.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/index.test.tsx @@ -63,9 +63,12 @@ jest.mock('../use_attack_discovery', () => ({ approximateFutureTime: null, attackDiscoveries: [], cachedAttackDiscoveries: {}, + didInitialFetch: true, fetchAttackDiscoveries: jest.fn(), + failureReason: null, generationIntervals: undefined, isLoading: false, + isLoadingPost: false, lastUpdated: null, replacements: {}, }), diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/index.tsx index 809a97c98c03c..f43360ec17666 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/index.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import { EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui'; +import { EuiEmptyPrompt, EuiFlexGroup, EuiFlexItem, EuiLoadingLogo, EuiSpacer } from '@elastic/eui'; import { css } from '@emotion/react'; import { ATTACK_DISCOVERY_STORAGE_KEY, @@ -13,7 +13,7 @@ import { useAssistantContext, useLoadConnectors, } from '@kbn/elastic-assistant'; -import type { Replacements } from '@kbn/elastic-assistant-common'; +import type { AttackDiscoveries, Replacements } from '@kbn/elastic-assistant-common'; import { uniq } from 'lodash/fp'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { useLocalStorage } from 'react-use'; @@ -37,7 +37,6 @@ import { PageTitle } from './page_title'; import { Summary } from './summary'; import { Upgrade } from './upgrade'; import { useAttackDiscovery } from '../use_attack_discovery'; -import type { AttackDiscovery } from '../types'; const AttackDiscoveryPageComponent: React.FC = () => { const spaceId = useSpaceId() ?? 'default'; @@ -72,31 +71,32 @@ const AttackDiscoveryPageComponent: React.FC = () => { alertsContextCount, approximateFutureTime, attackDiscoveries, - cachedAttackDiscoveries, + didInitialFetch, + failureReason, fetchAttackDiscoveries, generationIntervals, + onCancel, isLoading, + isLoadingPost, lastUpdated, replacements, } = useAttackDiscovery({ connectorId, - setConnectorId, setLoadingConnectorId, }); // get last updated from the cached attack discoveries if it exists: const [selectedConnectorLastUpdated, setSelectedConnectorLastUpdated] = useState( - cachedAttackDiscoveries[connectorId ?? '']?.updated ?? null + lastUpdated ?? null ); // get cached attack discoveries if they exist: - const [selectedConnectorAttackDiscoveries, setSelectedConnectorAttackDiscoveries] = useState< - AttackDiscovery[] - >(cachedAttackDiscoveries[connectorId ?? '']?.attackDiscoveries ?? []); + const [selectedConnectorAttackDiscoveries, setSelectedConnectorAttackDiscoveries] = + useState(attackDiscoveries ?? []); // get replacements from the cached attack discoveries if they exist: const [selectedConnectorReplacements, setSelectedConnectorReplacements] = useState( - cachedAttackDiscoveries[connectorId ?? '']?.replacements ?? {} + replacements ?? {} ); // the number of unique alerts in the attack discoveries: @@ -114,27 +114,12 @@ const AttackDiscoveryPageComponent: React.FC = () => { // update the connector ID in local storage: setConnectorId(selectedConnectorId); setLocalStorageAttackDiscoveryConnectorId(selectedConnectorId); - - // get the cached attack discoveries for the selected connector: - const cached = cachedAttackDiscoveries[selectedConnectorId]; - if (cached != null) { - setSelectedConnectorReplacements(cached.replacements ?? {}); - setSelectedConnectorAttackDiscoveries(cached.attackDiscoveries ?? []); - setSelectedConnectorLastUpdated(cached.updated ?? null); - } else { - setSelectedConnectorReplacements({}); - setSelectedConnectorAttackDiscoveries([]); - setSelectedConnectorLastUpdated(null); - } }, - [cachedAttackDiscoveries, setLocalStorageAttackDiscoveryConnectorId] + [setLocalStorageAttackDiscoveryConnectorId] ); // get connector intervals from generation intervals: - const connectorIntervals = useMemo( - () => generationIntervals?.[connectorId ?? ''] ?? [], - [connectorId, generationIntervals] - ); + const connectorIntervals = useMemo(() => generationIntervals ?? [], [generationIntervals]); const pageTitle = useMemo(() => , []); @@ -182,73 +167,82 @@ const AttackDiscoveryPageComponent: React.FC = () => { connectorId={connectorId} connectorsAreConfigured={aiConnectors != null && aiConnectors.length > 0} isLoading={isLoading} + // disable header actions before post request has completed + isDisabledActions={isLoadingPost} onConnectorIdSelected={onConnectorIdSelected} onGenerate={onGenerate} + onCancel={onCancel} /> - - {showSummary({ - attackDiscoveriesCount, - connectorId, - loadingConnectorId, - }) && ( - - )} - - <> - {showLoading({ - attackDiscoveriesCount, - connectorId, - isLoading, - loadingConnectorId, - }) ? ( - - ) : ( - selectedConnectorAttackDiscoveries.map((attackDiscovery, i) => ( - - } /> + ) : ( + <> + {showSummary({ + attackDiscoveriesCount, + connectorId, + loadingConnectorId, + }) && ( + + )} + + <> + {showLoading({ + attackDiscoveriesCount, + connectorId, + isLoading: isLoading || isLoadingPost, + loadingConnectorId, + }) ? ( + - - - )) - )} - - - - - - - + ) : ( + selectedConnectorAttackDiscoveries.map((attackDiscovery, i) => ( + + + + + )) + )} + + + + + + + + + )} diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.tsx index 8a61704ef7361..f691e508a47ff 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.tsx @@ -18,10 +18,10 @@ import { css } from '@emotion/react'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; import moment from 'moment'; +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; import { useKibana } from '../../../../common/lib/kibana'; import { getTimerPrefix } from './last_times_popover/helpers'; -import type { GenerationInterval } from '../../../types'; import { InfoPopoverBody } from '../info_popover_body'; const TEXT_COLOR = '#343741'; @@ -48,17 +48,21 @@ const CountdownComponent: React.FC = ({ approximateFutureTime, connectorI useEffect(() => { // periodically update the formatted date as time passes: + if (approximateFutureTime === null) { + return; + } const intervalId = setInterval(() => { - const now = moment(); - - const duration = moment(approximateFutureTime).isSameOrAfter(now) - ? moment.duration(moment(approximateFutureTime).diff(now)) - : moment.duration(now.diff(approximateFutureTime)); + setPrefix(getTimerPrefix(approximateFutureTime)); + if (approximateFutureTime !== null) { + const now = moment(); - const text = moment.utc(duration.asMilliseconds()).format('mm:ss'); + const duration = moment(approximateFutureTime).isSameOrAfter(now) + ? moment.duration(moment(approximateFutureTime).diff(now)) + : moment.duration(now.diff(approximateFutureTime)); - setPrefix(getTimerPrefix(approximateFutureTime)); - setTimerText(text); + const text = moment.utc(duration.asMilliseconds()).format('mm:ss'); + setTimerText(text); + } }, 1000); return () => clearInterval(intervalId); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/generation_timing/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/generation_timing/index.tsx index 67e1ebe592b11..e05374f7ccee1 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/generation_timing/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/generation_timing/index.tsx @@ -7,13 +7,14 @@ import { EuiFlexGroup, EuiFlexItem, EuiBadge, EuiText, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; +import moment from 'moment'; import React, { useMemo } from 'react'; import { PreferenceFormattedDate } from '../../../../../../common/components/formatted_date'; import { useKibana } from '../../../../../../common/lib/kibana'; import { MAX_SECONDS_BADGE_WIDTH } from '../helpers'; import * as i18n from '../translations'; -import type { GenerationInterval } from '../../../../../types'; interface Props { interval: GenerationInterval; @@ -51,7 +52,7 @@ const GenerationTimingComponent: React.FC = ({ interval }) => { data-test-subj="date" size="xs" > - + diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/helpers.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/helpers.ts index 3ce1e1f411641..9d8a0c4792eae 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/helpers.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/helpers.ts @@ -5,10 +5,10 @@ * 2.0. */ +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; import moment from 'moment'; import { APPROXIMATE_TIME_REMAINING, ABOVE_THE_AVERAGE_TIME } from '../translations'; -import type { GenerationInterval } from '../../../../types'; export const MAX_SECONDS_BADGE_WIDTH = 64; // px diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/index.tsx index 89925fdd33d4c..b1a24f0a3b079 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/index.tsx @@ -8,10 +8,10 @@ import { EuiFlexGroup, EuiFlexItem, EuiSpacer, EuiText, useEuiTheme } from '@elastic/eui'; import { css } from '@emotion/react'; import React, { useMemo } from 'react'; +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; import { useKibana } from '../../../../../common/lib/kibana'; import * as i18n from './translations'; -import type { GenerationInterval } from '../../../../types'; import { GenerationTiming } from './generation_timing'; interface Props { diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/index.tsx index b9d2737db1647..7e392e3165711 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/index.tsx @@ -9,10 +9,10 @@ import { EuiFlexGroup, EuiFlexItem, EuiLoadingElastic, useEuiTheme } from '@elas import { css } from '@emotion/react'; import React, { useMemo } from 'react'; +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; import { useKibana } from '../../../common/lib/kibana'; import { Countdown } from './countdown'; import { LoadingMessages } from './loading_messages'; -import type { GenerationInterval } from '../../types'; const BACKGROUND_COLOR_LIGHT = '#E6F1FA'; const BACKGROUND_COLOR_DARK = '#0B2030'; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/info_popover_body/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/info_popover_body/index.tsx index 3355a3041c0f2..1c1416acc09ac 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/info_popover_body/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/info_popover_body/index.tsx @@ -7,6 +7,7 @@ import { EuiBadge, EuiFlexGroup, EuiFlexItem, EuiPopoverTitle, EuiText } from '@elastic/eui'; import { css } from '@emotion/react'; +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; import React, { useMemo } from 'react'; import { useKibana } from '../../../../common/lib/kibana'; @@ -17,7 +18,6 @@ import { } from '../countdown/last_times_popover/helpers'; import { SECONDS_ABBREVIATION } from '../countdown/last_times_popover/translations'; import { AVERAGE_TIME } from '../countdown/translations'; -import type { GenerationInterval } from '../../../types'; const TEXT_COLOR = '#343741'; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.test.ts deleted file mode 100644 index dd5932bbb3dd7..0000000000000 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.test.ts +++ /dev/null @@ -1,180 +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 type { GenerationInterval } from '../../types'; -import { - encodeGenerationIntervals, - decodeGenerationIntervals, - getLocalStorageGenerationIntervals, - setLocalStorageGenerationIntervals, -} from '.'; - -const key = 'elasticAssistantDefault.attackDiscovery.default.generationIntervals'; - -const generationIntervals: Record = { - 'test-connector-1': [ - { - connectorId: 'test-connector-1', - date: new Date('2024-05-16T14:13:09.838Z'), - durationMs: 173648, - }, - { - connectorId: 'test-connector-1', - date: new Date('2024-05-16T13:59:49.620Z'), - durationMs: 146605, - }, - { - connectorId: 'test-connector-1', - date: new Date('2024-05-16T13:47:00.629Z'), - durationMs: 255163, - }, - ], - testConnector2: [ - { - connectorId: 'testConnector2', - date: new Date('2024-05-16T14:26:25.273Z'), - durationMs: 130447, - }, - ], - testConnector3: [ - { - connectorId: 'testConnector3', - date: new Date('2024-05-16T14:36:53.171Z'), - durationMs: 46614, - }, - { - connectorId: 'testConnector3', - date: new Date('2024-05-16T14:27:17.187Z'), - durationMs: 44129, - }, - ], -}; - -describe('storage', () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - describe('encodeGenerationIntervals', () => { - it('returns null when generationIntervals is invalid', () => { - const invalidGenerationIntervals: Record = - 1n as unknown as Record; // <-- invalid - - const result = encodeGenerationIntervals(invalidGenerationIntervals); - - expect(result).toBeNull(); - }); - - it('returns the expected encoded generationIntervals', () => { - const result = encodeGenerationIntervals(generationIntervals); - - expect(result).toEqual(JSON.stringify(generationIntervals)); - }); - }); - - describe('decodeGenerationIntervals', () => { - it('returns null when generationIntervals is invalid', () => { - const invalidGenerationIntervals = 'invalid generation intervals'; // <-- invalid - - const result = decodeGenerationIntervals(invalidGenerationIntervals); - - expect(result).toBeNull(); - }); - - it('returns the expected decoded generation intervals', () => { - const encoded = encodeGenerationIntervals(generationIntervals) ?? ''; // <-- valid intervals - - const result = decodeGenerationIntervals(encoded); - - expect(result).toEqual(generationIntervals); - }); - - it('parses date strings into Date objects', () => { - const encoded = JSON.stringify({ - 'test-connector-1': [ - { - connectorId: 'test-connector-1', - date: '2024-05-16T14:13:09.838Z', - durationMs: 173648, - }, - ], - }); - - const result = decodeGenerationIntervals(encoded); - - expect(result).toEqual({ - 'test-connector-1': [ - { - connectorId: 'test-connector-1', - date: new Date('2024-05-16T14:13:09.838Z'), - durationMs: 173648, - }, - ], - }); - }); - - it('returns null when date is not a string', () => { - const encoded = JSON.stringify({ - 'test-connector-1': [ - { - connectorId: 'test-connector-1', - date: 1234, // <-- invalid - durationMs: 173648, - }, - ], - }); - - const result = decodeGenerationIntervals(encoded); - - expect(result).toBeNull(); - }); - }); - - describe('getLocalStorageGenerationIntervals', () => { - it('returns null when the key is empty', () => { - const result = getLocalStorageGenerationIntervals(''); // <-- empty key - - expect(result).toBeNull(); - }); - - it('returns null the key is unknown', () => { - const result = getLocalStorageGenerationIntervals('unknown key'); // <-- unknown key - - expect(result).toBeNull(); - }); - - it('returns null when the generation intervals are invalid', () => { - localStorage.setItem(key, 'invalid generation intervals'); // <-- invalid - - const result = getLocalStorageGenerationIntervals(key); - - expect(result).toBeNull(); - }); - - it('returns the expected decoded generation intervals', () => { - const encoded = encodeGenerationIntervals(generationIntervals) ?? ''; // <-- valid intervals - localStorage.setItem(key, encoded); - - const decoded = decodeGenerationIntervals(encoded); - const result = getLocalStorageGenerationIntervals(key); - - expect(result).toEqual(decoded); - }); - }); - - describe('setLocalStorageGenerationIntervals', () => { - const localStorageSetItemSpy = jest.spyOn(Storage.prototype, 'setItem'); - - it('sets the encoded generation intervals in localStorage', () => { - const encoded = encodeGenerationIntervals(generationIntervals) ?? ''; - - setLocalStorageGenerationIntervals({ key, generationIntervals }); - - expect(localStorageSetItemSpy).toHaveBeenCalledWith(key, encoded); - }); - }); -}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.ts deleted file mode 100644 index 8c8c49b482650..0000000000000 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/session_storage/index.ts +++ /dev/null @@ -1,120 +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 type { Replacements } from '@kbn/elastic-assistant-common'; -import { isEmpty } from 'lodash/fp'; - -import type { AttackDiscovery, GenerationInterval } from '../../types'; - -export interface CachedAttackDiscoveries { - connectorId: string; - updated: Date; - attackDiscoveries: AttackDiscovery[]; - replacements: Replacements; -} - -export const encodeCachedAttackDiscoveries = ( - cachedAttackDiscoveries: Record -): string | null => { - try { - return JSON.stringify(cachedAttackDiscoveries); - } catch { - return null; - } -}; - -export const decodeCachedAttackDiscoveries = ( - cachedAttackDiscoveries: string -): Record | null => { - try { - return JSON.parse(cachedAttackDiscoveries); - } catch { - return null; - } -}; - -export const getSessionStorageCachedAttackDiscoveries = ( - key: string -): Record | null => { - if (!isEmpty(key)) { - return decodeCachedAttackDiscoveries(sessionStorage.getItem(key) ?? ''); - } - - return null; -}; - -export const setSessionStorageCachedAttackDiscoveries = ({ - key, - cachedAttackDiscoveries, -}: { - key: string; - cachedAttackDiscoveries: Record; -}) => { - if (!isEmpty(key)) { - const encoded = encodeCachedAttackDiscoveries(cachedAttackDiscoveries); - - if (encoded != null) { - sessionStorage.setItem(key, encoded); - } - } -}; - -export const encodeGenerationIntervals = ( - generationIntervals: Record -): string | null => { - try { - return JSON.stringify(generationIntervals); - } catch { - return null; - } -}; - -export const decodeGenerationIntervals = ( - generationIntervals: string -): Record | null => { - const parseDate = (key: string, value: unknown) => { - if (key === 'date' && typeof value === 'string') { - return new Date(value); - } else if (key === 'date' && typeof value !== 'string') { - throw new Error('Invalid date'); - } else { - return value; - } - }; - - try { - return JSON.parse(generationIntervals, parseDate); - } catch { - return null; - } -}; - -export const getLocalStorageGenerationIntervals = ( - key: string -): Record | null => { - if (!isEmpty(key)) { - return decodeGenerationIntervals(localStorage.getItem(key) ?? ''); - } - - return null; -}; - -export const setLocalStorageGenerationIntervals = ({ - key, - generationIntervals, -}: { - key: string; - generationIntervals: Record; -}) => { - if (!isEmpty(key)) { - const encoded = encodeGenerationIntervals(generationIntervals); - - if (encoded != null) { - localStorage.setItem(key, encoded); - } - } -}; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/translations.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/translations.ts index 3f8b87a9058c2..57b6aac6f05ba 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/translations.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/translations.ts @@ -14,6 +14,20 @@ export const ERROR_GENERATING_ATTACK_DISCOVERIES = i18n.translate( } ); +export const ERROR_CANCELING_ATTACK_DISCOVERIES = i18n.translate( + 'xpack.securitySolution.attackDiscovery.errorCancelingAttackDiscoveriesToastTitle', + { + defaultMessage: 'Error canceling attack discoveries', + } +); + +export const CONNECTOR_ERROR = i18n.translate( + 'xpack.securitySolution.attackDiscovery.errorConnector', + { + defaultMessage: 'No connector selected, select a connector to use attack discovery', + } +); + export const SHOW_REAL_VALUES = i18n.translate( 'xpack.securitySolution.attackDiscovery.showRealValuesLabel', { diff --git a/x-pack/plugins/security_solution/public/attack_discovery/types.ts b/x-pack/plugins/security_solution/public/attack_discovery/types.ts deleted file mode 100644 index 5a5c490042d06..0000000000000 --- a/x-pack/plugins/security_solution/public/attack_discovery/types.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. - */ - -export interface AttackDiscovery { - alertIds: string[]; - detailsMarkdown: string; - entitySummaryMarkdown: string; - id: string; - mitreAttackTactics?: string[]; - summaryMarkdown: string; - title: string; -} - -/** Generation intervals measure the time it takes to generate attack discoveries */ -export interface GenerationInterval { - connectorId: string; - date: Date; - durationMs: number; -} diff --git a/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/helpers.ts b/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/helpers.ts index 34b3d9b8a4c20..f800651985217 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/helpers.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/helpers.ts @@ -56,14 +56,13 @@ const getAzureApiVersionParameter = (url: string): string | undefined => { }; export const getRequestBody = ({ - actionTypeId, alertsIndexPattern, anonymizationFields, - connectorId, + genAiConfig, knowledgeBase, + selectedConnector, traceOptions, }: { - actionTypeId: string; alertsIndexPattern: string | undefined; anonymizationFields: { page: number; @@ -82,14 +81,13 @@ export const getRequestBody = ({ namespace?: string | undefined; }>; }; - connectorId: string | undefined; + genAiConfig?: GenAiConfig; knowledgeBase: KnowledgeBaseConfig; + selectedConnector?: ActionConnector; traceOptions: TraceOptions; }): AttackDiscoveryPostRequestBody => ({ - actionTypeId, alertsIndexPattern: alertsIndexPattern ?? '', anonymizationFields: anonymizationFields?.data ?? [], - connectorId: connectorId ?? '', langSmithProject: isEmpty(traceOptions?.langSmithProject) ? undefined : traceOptions?.langSmithProject, @@ -99,4 +97,10 @@ export const getRequestBody = ({ size: knowledgeBase.latestAlerts, replacements: {}, // no need to re-use replacements in the current implementation subAction: 'invokeAI', // non-streaming + apiConfig: { + connectorId: selectedConnector?.id ?? '', + actionTypeId: selectedConnector?.actionTypeId ?? '', + provider: genAiConfig?.apiProvider, + model: genAiConfig?.defaultModel, + }, }); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/index.test.tsx new file mode 100644 index 0000000000000..a6ba1570c61ee --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/index.test.tsx @@ -0,0 +1,222 @@ +/* + * 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 { renderHook, act } from '@testing-library/react-hooks'; +import { useKibana } from '../../common/lib/kibana'; +import { useFetchAnonymizationFields } from '@kbn/elastic-assistant/impl/assistant/api/anonymization_fields/use_fetch_anonymization_fields'; +import { usePollApi } from '../hooks/use_poll_api'; +import { useAttackDiscovery } from '.'; +import { ERROR_GENERATING_ATTACK_DISCOVERIES } from '../pages/translations'; +import { useKibana as mockUseKibana } from '../../common/lib/kibana/__mocks__'; + +jest.mock( + '@kbn/elastic-assistant/impl/assistant/api/anonymization_fields/use_fetch_anonymization_fields' +); +jest.mock('../hooks/use_poll_api'); +jest.mock('../../common/lib/kibana'); +const mockedUseKibana = mockUseKibana(); + +const mockAssistantAvailability = jest.fn(() => ({ + hasAssistantPrivilege: true, +})); +const mockConnectors: unknown[] = [ + { + id: 'test-id', + name: 'OpenAI connector', + actionTypeId: '.gen-ai', + }, +]; +jest.mock('@kbn/elastic-assistant', () => ({ + AssistantOverlay: () =>
, + useAssistantContext: () => ({ + alertsIndexPattern: 'alerts-index-pattern', + assistantAvailability: mockAssistantAvailability(), + knowledgeBase: { + isEnabledRAGAlerts: true, + isEnabledKnowledgeBase: true, + latestAlerts: 20, + }, + }), + useLoadConnectors: () => ({ + isFetched: true, + data: mockConnectors, + }), +})); +const mockAttackDiscoveryPost = { + timestamp: '2024-06-13T17:50:59.409Z', + id: 'f48da2ca-b63e-4387-82d7-1423a68500aa', + backingIndex: '.ds-.kibana-elastic-ai-assistant-attack-discovery-default-2024.06.12-000001', + createdAt: '2024-06-13T17:50:59.409Z', + updatedAt: '2024-06-17T15:00:39.680Z', + users: [ + { + id: 'u_mGBROF_q5bmFCATbLXAcCwKa0k8JvONAwSruelyKA5E_0', + name: 'elastic', + }, + ], + namespace: 'default', + status: 'running', + alertsContextCount: 20, + apiConfig: { + connectorId: 'my-gpt4o-ai', + actionTypeId: '.gen-ai', + }, + attackDiscoveries: [], + replacements: { abcd: 'hostname' }, + generationIntervals: [ + { + date: '2024-06-13T17:52:47.619Z', + durationMs: 108214, + }, + ], + averageIntervalMs: 108214, +}; + +const mockAttackDiscoveries = [ + { + summaryMarkdown: + 'A critical malware incident involving {{ host.name c1f9889f-1f6b-4abc-8e65-02de89fe1054 }} and {{ user.name 71ca47cf-082e-4d35-a8e7-6e4fa4e175da }} has been detected. The malware, identified as AppPool.vbs, was executed with high privileges and attempted to evade detection.', + id: '2204421f-bb42-4b96-a200-016a5388a029', + title: 'Critical Malware Incident on Windows Host', + mitreAttackTactics: ['Initial Access', 'Execution', 'Defense Evasion'], + alertIds: [ + '43cf228ce034aeeb89a1ef41cd7fcdef1a3db574fa5237badf1fa9eaa3425c21', + '44ae9696784b3baeee75935f889e55ce77da338241230b5c488f90a8bace43e2', + '2479b1b1007952d3b6dc26344c89f44c1bb396de56f1655eca408135b3d05af8', + ], + detailsMarkdown: 'details', + entitySummaryMarkdown: + '{{ host.name c1f9889f-1f6b-4abc-8e65-02de89fe1054 }} and {{ user.name 71ca47cf-082e-4d35-a8e7-6e4fa4e175da }} are involved in a critical malware incident.', + timestamp: '2024-06-07T20:04:35.715Z', + }, +]; +const setLoadingConnectorId = jest.fn(); + +describe('useAttackDiscovery', () => { + const mockPollApi = { + cancelAttackDiscovery: jest.fn(), + data: null, + pollApi: jest.fn(), + status: 'succeeded', + }; + + beforeEach(() => { + jest.clearAllMocks(); + (useKibana as jest.Mock).mockReturnValue(mockedUseKibana); + (useFetchAnonymizationFields as jest.Mock).mockReturnValue({ data: [] }); + (usePollApi as jest.Mock).mockReturnValue(mockPollApi); + }); + + it('initializes with correct default values', () => { + const { result } = renderHook(() => + useAttackDiscovery({ connectorId: 'test-id', setLoadingConnectorId }) + ); + + expect(result.current.alertsContextCount).toBeNull(); + expect(result.current.approximateFutureTime).toBeNull(); + expect(result.current.attackDiscoveries).toEqual([]); + expect(result.current.failureReason).toBeNull(); + expect(result.current.generationIntervals).toEqual([]); + expect(result.current.isLoading).toBe(false); + expect(result.current.lastUpdated).toBeNull(); + expect(result.current.replacements).toEqual({}); + expect(mockPollApi.pollApi).toHaveBeenCalled(); + expect(setLoadingConnectorId).toHaveBeenCalledWith(null); + }); + + it('fetches attack discoveries and updates state correctly', async () => { + (mockedUseKibana.services.http.fetch as jest.Mock).mockResolvedValue(mockAttackDiscoveryPost); + + const { result } = renderHook(() => useAttackDiscovery({ connectorId: 'test-id' })); + await act(async () => { + await result.current.fetchAttackDiscoveries(); + }); + expect(mockedUseKibana.services.http.fetch).toHaveBeenCalledWith( + '/internal/elastic_assistant/attack_discovery', + { + body: '{"alertsIndexPattern":"alerts-index-pattern","anonymizationFields":[],"size":20,"replacements":{},"subAction":"invokeAI","apiConfig":{"connectorId":"test-id","actionTypeId":".gen-ai"}}', + method: 'POST', + version: '1', + } + ); + // called on mount, and after successful fetch + expect(mockPollApi.pollApi).toHaveBeenCalledTimes(2); + expect(result.current.isLoading).toBe(true); + }); + + it('handles fetch errors correctly', async () => { + const errorMessage = 'Fetch error'; + const error = new Error(errorMessage); + (mockedUseKibana.services.http.fetch as jest.Mock).mockRejectedValue(error); + + const { result } = renderHook(() => useAttackDiscovery({ connectorId: 'test-id' })); + + await act(async () => { + await result.current.fetchAttackDiscoveries(); + }); + + expect(mockedUseKibana.services.notifications.toasts.addDanger).toHaveBeenCalledWith(error, { + title: ERROR_GENERATING_ATTACK_DISCOVERIES, + text: errorMessage, + }); + expect(result.current.isLoading).toBe(false); + }); + + it('sets loading state based on poll status', async () => { + (usePollApi as jest.Mock).mockReturnValue({ ...mockPollApi, status: 'running' }); + const { result } = renderHook(() => + useAttackDiscovery({ connectorId: 'test-id', setLoadingConnectorId }) + ); + + expect(result.current.isLoading).toBe(true); + expect(setLoadingConnectorId).toHaveBeenCalledWith('test-id'); + }); + + it('sets state based off of poll data', () => { + (usePollApi as jest.Mock).mockReturnValue({ + ...mockPollApi, + data: { + ...mockAttackDiscoveryPost, + status: 'succeeded', + attackDiscoveries: mockAttackDiscoveries, + connectorId: 'test-id', + }, + status: 'succeeded', + }); + const { result } = renderHook(() => useAttackDiscovery({ connectorId: 'test-id' })); + + expect(result.current.alertsContextCount).toEqual(20); + // this is set from usePollApi + expect(result.current.approximateFutureTime).toBeNull(); + + expect(result.current.attackDiscoveries).toEqual(mockAttackDiscoveries); + expect(result.current.failureReason).toBeNull(); + expect(result.current.generationIntervals).toEqual(mockAttackDiscoveryPost.generationIntervals); + expect(result.current.isLoading).toBe(false); + expect(result.current.lastUpdated).toEqual(new Date(mockAttackDiscoveries[0].timestamp)); + expect(result.current.replacements).toEqual(mockAttackDiscoveryPost.replacements); + }); + + it('sets state based off of failed poll data', () => { + (usePollApi as jest.Mock).mockReturnValue({ + ...mockPollApi, + data: { + ...mockAttackDiscoveryPost, + status: 'failed', + failureReason: 'something bad', + connectorId: 'test-id', + }, + status: 'failed', + }); + const { result } = renderHook(() => useAttackDiscovery({ connectorId: 'test-id' })); + + expect(result.current.failureReason).toEqual('something bad'); + expect(result.current.isLoading).toBe(false); + expect(result.current.lastUpdated).toEqual(null); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/index.tsx index 1a768d9d21b72..d517d5d0cd4ab 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/index.tsx @@ -5,71 +5,47 @@ * 2.0. */ -import { - ATTACK_DISCOVERY_STORAGE_KEY, - DEFAULT_ASSISTANT_NAMESPACE, - useAssistantContext, - useLoadConnectors, -} from '@kbn/elastic-assistant'; -import type { Replacements } from '@kbn/elastic-assistant-common'; +import { useAssistantContext, useLoadConnectors } from '@kbn/elastic-assistant'; +import type { + AttackDiscoveries, + Replacements, + GenerationInterval, +} from '@kbn/elastic-assistant-common'; import { AttackDiscoveryPostResponse, ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, } from '@kbn/elastic-assistant-common'; -import { uniq } from 'lodash/fp'; -import moment from 'moment'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; -import * as uuid from 'uuid'; import { useFetchAnonymizationFields } from '@kbn/elastic-assistant/impl/assistant/api/anonymization_fields/use_fetch_anonymization_fields'; -import { useSpaceId } from '../../common/hooks/use_space_id'; +import { usePollApi } from '../hooks/use_poll_api'; import { useKibana } from '../../common/lib/kibana'; -import { replaceNewlineLiterals } from '../helpers'; -import { useAttackDiscoveryTelemetry } from '../hooks/use_attack_discovery_telemetry'; -import { - CACHED_ATTACK_DISCOVERIES_SESSION_STORAGE_KEY, - GENERATION_INTERVALS_LOCAL_STORAGE_KEY, - getErrorToastText, - getFallbackActionTypeId, -} from '../pages/helpers'; -import { getAverageIntervalSeconds } from '../pages/loading_callout/countdown/last_times_popover/helpers'; -import type { CachedAttackDiscoveries } from '../pages/session_storage'; -import { - getLocalStorageGenerationIntervals, - getSessionStorageCachedAttackDiscoveries, - setLocalStorageGenerationIntervals, - setSessionStorageCachedAttackDiscoveries, -} from '../pages/session_storage'; -import { ERROR_GENERATING_ATTACK_DISCOVERIES } from '../pages/translations'; -import type { AttackDiscovery, GenerationInterval } from '../types'; +import { getErrorToastText } from '../pages/helpers'; +import { CONNECTOR_ERROR, ERROR_GENERATING_ATTACK_DISCOVERIES } from '../pages/translations'; import { getGenAiConfig, getRequestBody } from './helpers'; -const MAX_GENERATION_INTERVALS = 5; - export interface UseAttackDiscovery { alertsContextCount: number | null; approximateFutureTime: Date | null; - attackDiscoveries: AttackDiscovery[]; - cachedAttackDiscoveries: Record; + attackDiscoveries: AttackDiscoveries; + didInitialFetch: boolean; + failureReason: string | null; fetchAttackDiscoveries: () => Promise; - generationIntervals: Record | undefined; + generationIntervals: GenerationInterval[] | undefined; isLoading: boolean; + isLoadingPost: boolean; lastUpdated: Date | null; + onCancel: () => Promise; replacements: Replacements; } export const useAttackDiscovery = ({ connectorId, - setConnectorId, setLoadingConnectorId, }: { connectorId: string | undefined; - setConnectorId?: (connectorId: string | undefined) => void; setLoadingConnectorId?: (loadingConnectorId: string | null) => void; }): UseAttackDiscovery => { - const { reportAttackDiscoveriesGenerated } = useAttackDiscoveryTelemetry(); - const spaceId: string | undefined = useSpaceId(); - // get Kibana services and connectors const { http, @@ -79,6 +55,18 @@ export const useAttackDiscovery = ({ http, }); + // generation can take a long time, so we calculate an approximate future time: + const [approximateFutureTime, setApproximateFutureTime] = useState(null); + // whether post request is loading (dont show actions) + const [isLoadingPost, setIsLoadingPost] = useState(false); + const { + cancelAttackDiscovery, + data: pollData, + pollApi, + status: pollStatus, + didInitialFetch, + } = usePollApi({ http, setApproximateFutureTime, toasts, connectorId }); + // loading boilerplate: const [isLoading, setIsLoading] = useState(false); @@ -87,245 +75,124 @@ export const useAttackDiscovery = ({ const { data: anonymizationFields } = useFetchAnonymizationFields(); - const sessionStorageKey = useMemo( - () => - spaceId != null // spaceId is undefined while the useSpaceId hook is loading - ? `${DEFAULT_ASSISTANT_NAMESPACE}.${ATTACK_DISCOVERY_STORAGE_KEY}.${spaceId}.${CACHED_ATTACK_DISCOVERIES_SESSION_STORAGE_KEY}` - : '', - [spaceId] - ); - - const [cachedAttackDiscoveries, setCachedAttackDiscoveries] = useState< - Record - >({}); - - useEffect(() => { - const decoded = getSessionStorageCachedAttackDiscoveries(sessionStorageKey); - - if (decoded != null) { - setCachedAttackDiscoveries(decoded); - - const decodedAttackDiscoveries = decoded[connectorId ?? '']?.attackDiscoveries; - if (decodedAttackDiscoveries != null) { - setAttackDiscoveries(decodedAttackDiscoveries); - } - - const decodedReplacements = decoded[connectorId ?? '']?.replacements; - if (decodedReplacements != null) { - setReplacements(decodedReplacements); - } - - const decodedLastUpdated = decoded[connectorId ?? '']?.updated; - if (decodedLastUpdated != null) { - setLastUpdated(decodedLastUpdated); - } - } - }, [connectorId, sessionStorageKey]); - - const localStorageKey = useMemo( - () => - spaceId != null // spaceId is undefined while the useSpaceId hook is loading - ? `${DEFAULT_ASSISTANT_NAMESPACE}.${ATTACK_DISCOVERY_STORAGE_KEY}.${spaceId}.${GENERATION_INTERVALS_LOCAL_STORAGE_KEY}` - : '', - [spaceId] - ); - - const [generationIntervals, setGenerationIntervals] = React.useState< - Record | undefined - >(undefined); - - useEffect(() => { - const decoded = getLocalStorageGenerationIntervals(localStorageKey); - - if (decoded != null) { - setGenerationIntervals(decoded); - } - }, [localStorageKey]); - - // get connector intervals from generation intervals: - const connectorIntervals = useMemo( - () => generationIntervals?.[connectorId ?? ''] ?? [], - [connectorId, generationIntervals] - ); - - // generation can take a long time, so we calculate an approximate future time: - const [approximateFutureTime, setApproximateFutureTime] = useState(null); - - // get cached attack discoveries if they exist: - const [attackDiscoveries, setAttackDiscoveries] = useState( - cachedAttackDiscoveries[connectorId ?? '']?.attackDiscoveries ?? [] - ); - - // get replacements from the cached attack discoveries if they exist: - const [replacements, setReplacements] = useState( - cachedAttackDiscoveries[connectorId ?? '']?.replacements ?? {} - ); - - // get last updated from the cached attack discoveries if it exists: - const [lastUpdated, setLastUpdated] = useState( - cachedAttackDiscoveries[connectorId ?? '']?.updated ?? null - ); + const [generationIntervals, setGenerationIntervals] = React.useState([]); + const [attackDiscoveries, setAttackDiscoveries] = useState([]); + const [replacements, setReplacements] = useState({}); + const [lastUpdated, setLastUpdated] = useState(null); + const [failureReason, setFailureReason] = useState(null); // number of alerts sent as context to the LLM: const [alertsContextCount, setAlertsContextCount] = useState(null); - /** The callback when users click the Generate button */ - const fetchAttackDiscoveries = useCallback(async () => { + const requestBody = useMemo(() => { const selectedConnector = aiConnectors?.find((connector) => connector.id === connectorId); - const actionTypeId = getFallbackActionTypeId(selectedConnector?.actionTypeId); - - const body = getRequestBody({ - actionTypeId, + const genAiConfig = getGenAiConfig(selectedConnector); + return getRequestBody({ alertsIndexPattern, anonymizationFields, - connectorId, + genAiConfig, knowledgeBase, + selectedConnector, traceOptions, }); + }, [ + aiConnectors, + alertsIndexPattern, + anonymizationFields, + connectorId, + knowledgeBase, + traceOptions, + ]); + + useEffect(() => { + if (connectorId != null && connectorId !== '') { + pollApi(); + setLoadingConnectorId?.(connectorId); + setAlertsContextCount(null); + setFailureReason(null); + setLastUpdated(null); + setReplacements({}); + setAttackDiscoveries([]); + setGenerationIntervals([]); + } + }, [pollApi, connectorId, setLoadingConnectorId]); + useEffect(() => { + if (pollStatus === 'running') { + setIsLoading(true); + setLoadingConnectorId?.(connectorId ?? null); + } else { + setIsLoading(false); + setLoadingConnectorId?.(null); + } + }, [pollStatus, connectorId, setLoadingConnectorId]); + + useEffect(() => { + if (pollData !== null && pollData.connectorId === connectorId) { + if (pollData.alertsContextCount != null) setAlertsContextCount(pollData.alertsContextCount); + if (pollData.attackDiscoveries.length) { + // get last updated from timestamp, not from updatedAt since this can indicate the last time the status was updated + setLastUpdated(new Date(pollData.attackDiscoveries[0].timestamp)); + } + if (pollData.replacements) setReplacements(pollData.replacements); + if (pollData.status === 'failed' && pollData.failureReason) { + setFailureReason(pollData.failureReason); + } else { + setFailureReason(null); + } + setAttackDiscoveries(pollData.attackDiscoveries); + setGenerationIntervals(pollData.generationIntervals); + } + }, [connectorId, pollData]); + + /** The callback when users click the Generate button */ + const fetchAttackDiscoveries = useCallback(async () => { try { + if (requestBody.apiConfig.connectorId === '' || requestBody.apiConfig.actionTypeId === '') { + throw new Error(CONNECTOR_ERROR); + } setLoadingConnectorId?.(connectorId ?? null); setIsLoading(true); + setIsLoadingPost(true); setApproximateFutureTime(null); - - const averageIntervalSeconds = getAverageIntervalSeconds(connectorIntervals); - setApproximateFutureTime(moment().add(averageIntervalSeconds, 'seconds').toDate()); - - const startTime = moment(); // start timing the generation - // call the internal API to generate attack discoveries: const rawResponse = await http.fetch('/internal/elastic_assistant/attack_discovery', { - body: JSON.stringify(body), + body: JSON.stringify(requestBody), method: 'POST', version: ELASTIC_AI_ASSISTANT_INTERNAL_API_VERSION, }); - + setIsLoadingPost(false); const parsedResponse = AttackDiscoveryPostResponse.safeParse(rawResponse); + if (!parsedResponse.success) { throw new Error('Failed to parse the response'); } - const endTime = moment(); - const durationMs = endTime.diff(startTime); - - // update the cached attack discoveries with the new discoveries: - const newAttackDiscoveries: AttackDiscovery[] = - parsedResponse.data.attackDiscoveries?.map((attackDiscovery) => ({ - alertIds: [...attackDiscovery.alertIds], - detailsMarkdown: replaceNewlineLiterals(attackDiscovery.detailsMarkdown), - entitySummaryMarkdown: replaceNewlineLiterals(attackDiscovery.entitySummaryMarkdown), - id: uuid.v4(), - mitreAttackTactics: attackDiscovery.mitreAttackTactics, - summaryMarkdown: replaceNewlineLiterals(attackDiscovery.summaryMarkdown), - title: attackDiscovery.title, - })) ?? []; - - const responseReplacements = parsedResponse.data.replacements ?? {}; - const newReplacements = { ...replacements, ...responseReplacements }; - - const newLastUpdated = new Date(); - - const newCachedAttackDiscoveries = { - ...cachedAttackDiscoveries, - [connectorId ?? '']: { - connectorId: connectorId ?? '', - attackDiscoveries: newAttackDiscoveries, - replacements: newReplacements, - updated: newLastUpdated, - }, - }; - - setCachedAttackDiscoveries(newCachedAttackDiscoveries); - setSessionStorageCachedAttackDiscoveries({ - key: sessionStorageKey, - cachedAttackDiscoveries: newCachedAttackDiscoveries, - }); - - // update the generation intervals with the latest timing: - const previousConnectorIntervals: GenerationInterval[] = - generationIntervals != null ? generationIntervals[connectorId ?? ''] ?? [] : []; - const newInterval: GenerationInterval = { - connectorId: connectorId ?? '', - date: new Date(), - durationMs, - }; - - const newConnectorIntervals = [newInterval, ...previousConnectorIntervals].slice( - 0, - MAX_GENERATION_INTERVALS - ); - const newGenerationIntervals: Record = { - ...generationIntervals, - [connectorId ?? '']: newConnectorIntervals, - }; - - const newAlertsContextCount = parsedResponse.data.alertsContextCount ?? null; - setAlertsContextCount(newAlertsContextCount); - - // only update the generation intervals if alerts were sent as context to the LLM: - if (newAlertsContextCount != null && newAlertsContextCount > 0) { - setGenerationIntervals(newGenerationIntervals); - setLocalStorageGenerationIntervals({ - key: localStorageKey, - generationIntervals: newGenerationIntervals, - }); + if (parsedResponse.data.status === 'running') { + pollApi(); } - - setReplacements(newReplacements); - setAttackDiscoveries(newAttackDiscoveries); - setLastUpdated(newLastUpdated); - setConnectorId?.(connectorId); - const connectorConfig = getGenAiConfig(selectedConnector); - reportAttackDiscoveriesGenerated({ - actionTypeId, - durationMs, - alertsContextCount: newAlertsContextCount ?? 0, - alertsCount: uniq( - newAttackDiscoveries.flatMap((attackDiscovery) => attackDiscovery.alertIds) - ).length, - configuredAlertsCount: knowledgeBase.latestAlerts, - provider: connectorConfig?.apiProvider, - model: connectorConfig?.defaultModel, - }); } catch (error) { + setIsLoadingPost(false); + setIsLoading(false); toasts?.addDanger(error, { title: ERROR_GENERATING_ATTACK_DISCOVERIES, text: getErrorToastText(error), }); - } finally { - setApproximateFutureTime(null); - setLoadingConnectorId?.(null); - setIsLoading(false); } - }, [ - aiConnectors, - alertsIndexPattern, - anonymizationFields, - cachedAttackDiscoveries, - connectorId, - connectorIntervals, - generationIntervals, - http, - knowledgeBase, - localStorageKey, - replacements, - reportAttackDiscoveriesGenerated, - sessionStorageKey, - setConnectorId, - setLoadingConnectorId, - toasts, - traceOptions, - ]); + }, [connectorId, http, pollApi, requestBody, setLoadingConnectorId, toasts]); return { alertsContextCount, approximateFutureTime, attackDiscoveries, - cachedAttackDiscoveries, + didInitialFetch, + failureReason, fetchAttackDiscoveries, generationIntervals, isLoading, + isLoadingPost, lastUpdated, + onCancel: cancelAttackDiscovery, replacements, }; }; diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/constants.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/constants.ts index b7893592296e9..d16fd182928de 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/constants.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/constants.ts @@ -60,7 +60,6 @@ export enum TelemetryEventTypes { AssetCriticalityCsvPreviewGenerated = 'Asset Criticality Csv Preview Generated', AssetCriticalityFileSelected = 'Asset Criticality File Selected', AssetCriticalityCsvImported = 'Asset Criticality CSV Imported', - AttackDiscoveriesGenerated = 'Attack Discoveries Generated', EntityDetailsClicked = 'Entity Details Clicked', EntityAlertsClicked = 'Entity Alerts Clicked', EntityRiskFiltered = 'Entity Risk Filtered', diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/index.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/index.ts deleted file mode 100644 index 4305556923c99..0000000000000 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/index.ts +++ /dev/null @@ -1,64 +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 type { TelemetryEvent } from '../../types'; -import { TelemetryEventTypes } from '../../constants'; - -export const insightsGeneratedEvent: TelemetryEvent = { - eventType: TelemetryEventTypes.AttackDiscoveriesGenerated, - schema: { - actionTypeId: { - type: 'keyword', - _meta: { - description: 'Kibana connector type', - optional: false, - }, - }, - durationMs: { - type: 'integer', - _meta: { - description: 'Duration of request in ms', - optional: false, - }, - }, - alertsContextCount: { - type: 'integer', - _meta: { - description: 'Number of alerts sent as context to the LLM', - optional: false, - }, - }, - alertsCount: { - type: 'integer', - _meta: { - description: 'Number of unique alerts referenced in the attack discoveries', - optional: false, - }, - }, - configuredAlertsCount: { - type: 'integer', - _meta: { - description: 'Number of alerts configured by the user', - optional: false, - }, - }, - model: { - type: 'keyword', - _meta: { - description: 'LLM model', - optional: true, - }, - }, - provider: { - type: 'keyword', - _meta: { - description: 'OpenAI provider', - optional: true, - }, - }, - }, -}; diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/types.ts deleted file mode 100644 index dc83083bd38e3..0000000000000 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/attack_discovery/types.ts +++ /dev/null @@ -1,26 +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 type { RootSchema } from '@kbn/core/public'; -import type { TelemetryEventTypes } from '../../constants'; - -export interface ReportAttackDiscoveriesGeneratedParams { - actionTypeId: string; - provider?: string; - model?: string; - durationMs: number; - alertsContextCount: number; - alertsCount: number; - configuredAlertsCount: number; -} - -export type ReportAttackDiscoveryTelemetryEventParams = ReportAttackDiscoveriesGeneratedParams; - -export interface AttackDiscoveryTelemetryEvent { - eventType: TelemetryEventTypes.AttackDiscoveriesGenerated; - schema: RootSchema; -} diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/telemetry_events.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/telemetry_events.ts index fa9875a027db6..8fe949fc783e7 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/events/telemetry_events.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/events/telemetry_events.ts @@ -28,7 +28,6 @@ import { assistantMessageSentEvent, assistantQuickPrompt, } from './ai_assistant'; -import { insightsGeneratedEvent } from './attack_discovery'; import { dataQualityIndexCheckedEvent, dataQualityCheckAllClickedEvent } from './data_quality'; import { DocumentDetailsFlyoutOpenedEvent, @@ -156,7 +155,6 @@ export const telemetryEvents = [ assistantMessageSentEvent, assistantQuickPrompt, assistantSettingToggledEvent, - insightsGeneratedEvent, entityClickedEvent, entityAlertsClickedEvent, entityRiskFilteredEvent, diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.mock.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.mock.ts index e1c4c8d4746cf..747a0a3a57770 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.mock.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.mock.ts @@ -35,5 +35,4 @@ export const createTelemetryClientMock = (): jest.Mocked = reportAssetCriticalityCsvPreviewGenerated: jest.fn(), reportAssetCriticalityFileSelected: jest.fn(), reportAssetCriticalityCsvImported: jest.fn(), - reportAttackDiscoveriesGenerated: jest.fn(), }); diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts index 3ca55ab75e685..266b3c737eb62 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts @@ -24,7 +24,6 @@ import type { ReportAssistantMessageSentParams, ReportAssistantQuickPromptParams, ReportAssistantSettingToggledParams, - ReportAttackDiscoveriesGeneratedParams, ReportRiskInputsExpandedFlyoutOpenedParams, ReportToggleRiskSummaryClickedParams, ReportDetailsFlyoutOpenedParams, @@ -74,10 +73,6 @@ export class TelemetryClient implements TelemetryClientStart { this.analytics.reportEvent(TelemetryEventTypes.AssistantSettingToggled, params); }; - public reportAttackDiscoveriesGenerated = (params: ReportAttackDiscoveriesGeneratedParams) => { - this.analytics.reportEvent(TelemetryEventTypes.AttackDiscoveriesGenerated, params); - }; - public reportEntityDetailsClicked = ({ entity }: ReportEntityDetailsClickedParams) => { this.analytics.reportEvent(TelemetryEventTypes.EntityDetailsClicked, { entity, diff --git a/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts b/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts index 3be54678c0ad8..9e7a49a91497e 100644 --- a/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts +++ b/x-pack/plugins/security_solution/public/common/lib/telemetry/types.ts @@ -6,11 +6,6 @@ */ import type { AnalyticsServiceSetup, RootSchema } from '@kbn/core/public'; -import type { - AttackDiscoveryTelemetryEvent, - ReportAttackDiscoveriesGeneratedParams, - ReportAttackDiscoveryTelemetryEventParams, -} from './events/attack_discovery/types'; import type { SecurityCellActionMetadata } from '../../../app/actions/types'; import type { ML_JOB_TELEMETRY_STATUS, TelemetryEventTypes } from './constants'; import type { @@ -61,7 +56,6 @@ import type { export * from './events/ai_assistant/types'; export * from './events/alerts_grouping/types'; -export * from './events/attack_discovery/types'; export * from './events/data_quality/types'; export * from './events/onboarding/types'; export type { @@ -108,7 +102,6 @@ export interface ReportBreadcrumbClickedParams { export type TelemetryEventParams = | ReportAlertsGroupingTelemetryEventParams | ReportAssistantTelemetryEventParams - | ReportAttackDiscoveryTelemetryEventParams | ReportEntityAnalyticsTelemetryEventParams | ReportMLJobUpdateParams | ReportCellActionClickedParams @@ -132,9 +125,6 @@ export interface TelemetryClientStart { reportAssistantQuickPrompt(params: ReportAssistantQuickPromptParams): void; reportAssistantSettingToggled(params: ReportAssistantSettingToggledParams): void; - // Attack discovery - reportAttackDiscoveriesGenerated(params: ReportAttackDiscoveriesGeneratedParams): void; - // Entity Analytics reportEntityDetailsClicked(params: ReportEntityDetailsClickedParams): void; reportEntityAlertsClicked(params: ReportEntityAlertsClickedParams): void; @@ -173,7 +163,6 @@ export type TelemetryEvent = | EntityAnalyticsTelemetryEvent | DataQualityTelemetryEvents | DocumentDetailsTelemetryEvents - | AttackDiscoveryTelemetryEvent | { eventType: TelemetryEventTypes.MLJobUpdate; schema: RootSchema; From a266f3939468136501227708f1fd9eeb3ae71557 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 25 Jun 2024 09:01:21 -0700 Subject: [PATCH 08/22] [CloudSecurity] Converting Findings Search bar FTR into integration test (#186557) ## Summary It closes #174472 This PR converts the SearchBar FTR test on the Findings page that was skipped due to faillures on CI into an integration test using MSW. Also, it adds the following changes: - Added a `generateCspFinding` helper to help with the writing of future tests and generating batch data. - Updated the `CspFinding` interface to reflect the latest integration changes. - Removed skipped FTR test - Moved fleetCspPackageHandler to the default handlers. - Removed some tests on the `configurations.test.tsx` that are already handled in the `no_findings_states.test.tsx` test. - Also added another test to check for the empty results component. - Updated SearchBar to include filter and query properties to make it use the urlQuery defined in the csp plugin. ## Screenshots ![image](https://github.com/elastic/kibana/assets/19270322/d3982cf0-a454-472e-a7cf-9e887386fd75) --- .../common/schemas/csp_finding.ts | 5 +- .../use_cloud_security_grouping.ts | 1 + .../no_findings_states.test.tsx | 5 - .../configurations.handlers.mock.ts | 236 +++++++++ .../configurations/configurations.test.tsx | 446 ++++++++++-------- .../pages/configurations/configurations.tsx | 5 +- .../latest_findings_container.tsx | 6 +- .../use_latest_findings_grouping.tsx | 2 + .../layout/findings_search_bar.tsx | 7 + .../use_latest_vulnerabilities_grouping.tsx | 2 + .../latest_vulnerabilities_container.tsx | 6 +- .../handlers/dataview.handlers.mock.ts | 47 ++ .../handlers/fleet.handlers.mock.ts} | 2 +- .../public/test/mock_server/handlers/index.ts | 8 +- .../pages/findings.ts | 35 -- 15 files changed, 553 insertions(+), 260 deletions(-) create mode 100644 x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.handlers.mock.ts create mode 100644 x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/dataview.handlers.mock.ts rename x-pack/plugins/cloud_security_posture/public/{components/no_findings_states/no_findings_states.handlers.mock.ts => test/mock_server/handlers/fleet.handlers.mock.ts} (89%) diff --git a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts b/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts index 5d10b5ee4c9a0..3033da7b043b9 100644 --- a/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts +++ b/x-pack/plugins/cloud_security_posture/common/schemas/csp_finding.ts @@ -11,7 +11,7 @@ import { CspBenchmarkRuleMetadata } from '../types/latest'; export interface CspFinding { '@timestamp': string; - cluster_id: string; + cluster_id?: string; orchestrator?: CspFindingOrchestrator; cloud?: CspFindingCloud; // only available on CSPM findings result: CspFindingResult; @@ -33,11 +33,12 @@ interface CspFindingOrchestrator { } interface CspFindingCloud { - provider: 'aws'; + provider: 'aws' | 'azure' | 'gcp'; account: { name: string; id: string; }; + region?: string; } interface CspFindingResult { diff --git a/x-pack/plugins/cloud_security_posture/public/components/cloud_security_grouping/use_cloud_security_grouping.ts b/x-pack/plugins/cloud_security_posture/public/components/cloud_security_grouping/use_cloud_security_grouping.ts index ea1aee0ffcef7..d9e7ac07b9dbd 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/cloud_security_grouping/use_cloud_security_grouping.ts +++ b/x-pack/plugins/cloud_security_posture/public/components/cloud_security_grouping/use_cloud_security_grouping.ts @@ -128,6 +128,7 @@ export const useCloudSecurityGrouping = ({ query, error, selectedGroup, + urlQuery, setUrlQuery, uniqueValue, isNoneSelected, diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.test.tsx b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.test.tsx index ad3e482f614f5..1dcb9454a176a 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.test.tsx @@ -12,7 +12,6 @@ import { renderWrapper } from '../../test/mock_server/mock_server_test_provider' import { NoFindingsStates } from './no_findings_states'; import * as statusHandlers from '../../../server/routes/status/status.handlers.mock'; import * as benchmarksHandlers from '../../../server/routes/benchmarks/benchmarks.handlers.mock'; -import { fleetCspPackageHandler } from './no_findings_states.handlers.mock'; const server = setupMockServer(); @@ -23,10 +22,6 @@ const renderNoFindingsStates = (postureType: 'cspm' | 'kspm' = 'cspm') => { describe('NoFindingsStates', () => { startMockServer(server); - beforeEach(() => { - server.use(fleetCspPackageHandler); - }); - it('shows integrations installation prompt with installation links when integration is not-installed', async () => { server.use(statusHandlers.notInstalledHandler); renderNoFindingsStates(); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.handlers.mock.ts new file mode 100644 index 0000000000000..38e4edf46f77a --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.handlers.mock.ts @@ -0,0 +1,236 @@ +/* + * 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 { estypes } from '@elastic/elasticsearch'; +import { CspFinding } from '../../../common/schemas/csp_finding'; +import { isArray } from 'lodash'; +import { http, HttpResponse } from 'msw'; +import { v4 as uuidV4 } from 'uuid'; + +export const generateCspFinding = ( + id: string, + evaluation: 'failed' | 'passed' = 'passed' +): CspFinding => { + const timeFiveHoursAgo = Date.now() - 18000000; + const timeFiveHoursAgoToIsoString = new Date(timeFiveHoursAgo).toISOString(); + + return { + agent: { + name: 'cloudbeatVM', + id: `agent-${id}`, + type: 'cloudbeat', + version: '8.13.2', + }, + resource: { + account_id: `/subscriptions/${id}`, + sub_type: 'azure-disk', + account_name: 'csp-team', + name: `disk_${id}`, + id: `/subscriptions/${id}/test/disks/disk_${id}`, + region: 'eastus', + type: 'cloud-compute', + raw: { + id: `/subscriptions/${id}/test/disks/disk_${id}`, + name: `disk_${id}`, + type: 'microsoft.compute/disks', + location: 'eastus', + properties: { + publicNetworkAccess: 'Enabled', + osType: 'Linux', + }, + }, + }, + rule: { + rego_rule_id: 'AZU-1.0-1.0', + references: 'https://elastic.co', + impact: `impact ${id}`, + description: `description ${id}`, + section: `Section ${id}`, + default_value: '', + version: '1.0', + rationale: `rationale ${id}`, + benchmark: { + name: 'CIS Microsoft Azure Foundations', + rule_number: `1.1.${id}`, + id: 'cis_azure', + version: 'v2.0.0', + posture_type: 'cspm', + }, + tags: ['CIS', 'AZURE', 'CIS 1.0', `Section ${id}`], + remediation: `remediation ${id}`, + audit: `audit ${id}`, + name: `Name ${id}`, + id: `rule-${id}`, + profile_applicability: 'profile', + }, + result: { + evaluation, + evidence: { + Resource: { + name: `disk_${id}`, + location: 'eastus', + type: 'microsoft.compute/disks', + properties: { + publicNetworkAccess: 'Enabled', + osType: 'Linux', + }, + }, + }, + }, + cloud: { + provider: 'azure', + region: 'eastus', + account: { + name: 'test', + id: `/subscriptions/${id}`, + }, + }, + '@timestamp': timeFiveHoursAgoToIsoString, + ecs: { + version: '8.6.0', + }, + host: { + name: `host ${id}`, + id: `host-${id}`, + containerized: false, + ip: ['0.0.0.0'], + mac: ['00:00:00:00:00:00'], + hostname: `host-${id}`, + architecture: 'x86_64', + os: { + kernel: '4.19.0-16-cloud-amd64', + codename: 'buster', + type: 'linux', + platform: 'debian', + version: '10.3', + family: 'debian', + name: 'Debian GNU/Linux', + }, + }, + event: { + agent_id_status: 'auth_metadata_missing', + sequence: 1715693351, + ingested: timeFiveHoursAgoToIsoString, + created: timeFiveHoursAgoToIsoString, + kind: 'state', + id: `event-${id}`, + type: ['info'], + category: ['configuration'], + dataset: 'cloud_security_posture.findings', + outcome: 'success', + }, + }; +}; + +export const generateFindingHit = (finding: CspFinding) => { + return { + _index: 'logs-cloud_security_posture.findings_latest-default', + _id: uuidV4(), + _score: null, + _source: finding, + sort: [1715693387715], + }; +}; + +const getFindingsBsearchResponse = (findings: CspFinding[]) => { + const buckets = findings.reduce( + (acc, finding) => { + if (finding.result.evaluation === 'failed') { + acc[0].doc_count = (acc[0].doc_count || 0) + 1; + } else { + acc[1].doc_count = (acc[1].doc_count || 0) + 1; + } + return acc; + }, + [ + { + key: 'failed', + doc_count: 0, + }, + { + key: 'passed', + doc_count: 0, + }, + ] + ); + + return { + id: 0, + result: { + rawResponse: { + took: 1, + timed_out: false, + _shards: { + total: 1, + successful: 1, + skipped: 0, + failed: 0, + }, + hits: { + total: findings.length, + max_score: null, + hits: findings.map(generateFindingHit), + }, + aggregations: { + count: { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets, + }, + }, + }, + isPartial: false, + isRunning: false, + total: 1, + loaded: 1, + isRestored: false, + }, + }; +}; + +export const rulesGetStatesHandler = http.get( + 'internal/cloud_security_posture/rules/_get_states', + () => { + return HttpResponse.json({}); + } +); + +export const bsearchFindingsHandler = (findings: CspFinding[]) => + http.post('internal/bsearch', async ({ request }) => { + const jsonRequest = (await request.json()) as Partial; + + const filter = jsonRequest?.query?.bool?.filter; + + const hasRuleSectionQuerySearchTerm = + isArray(filter) && + isArray(filter[0]?.bool?.should) && + filter[0]?.bool?.should?.[0]?.term?.['rule.section']?.value !== undefined; + + if (hasRuleSectionQuerySearchTerm) { + const filteredFindingJson = findings.filter((finding) => { + const termValue = (filter[0].bool?.should as estypes.QueryDslQueryContainer[])?.[0]?.term?.[ + 'rule.section' + ]?.value; + return finding.rule.section === termValue; + }); + + return HttpResponse.json(getFindingsBsearchResponse(filteredFindingJson)); + } + + const hasRuleSectionFilter = + isArray(filter) && filter?.[0]?.match_phrase?.['rule.section'] !== undefined; + + if (hasRuleSectionFilter) { + const filteredFindingJson = findings.filter((finding) => { + return finding.rule.section === filter?.[0]?.match_phrase?.['rule.section']; + }); + + return HttpResponse.json(getFindingsBsearchResponse(filteredFindingJson)); + } + + return HttpResponse.json(getFindingsBsearchResponse(findings)); + }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.test.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.test.tsx index c955cc847a6c9..221cb998d0654 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.test.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.test.tsx @@ -5,246 +5,276 @@ * 2.0. */ import React from 'react'; -import Chance from 'chance'; -import type { UseQueryResult } from '@tanstack/react-query'; -import { of } from 'rxjs'; -import { useDataView } from '../../common/api/use_data_view'; +import { + getMockServerDependencies, + setupMockServer, + startMockServer, +} from '../../test/mock_server/mock_server'; +import { renderWrapper } from '../../test/mock_server/mock_server_test_provider'; import { Configurations } from './configurations'; -import { TestProvider } from '../../test/test_provider'; -import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; -import { createStubDataView } from '@kbn/data-views-plugin/public/data_views/data_view.stub'; -import { CSP_LATEST_FINDINGS_DATA_VIEW } from '../../../common/constants'; -import * as TEST_SUBJECTS from './test_subjects'; -import type { DataView } from '@kbn/data-plugin/common'; -import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; -import { useSubscriptionStatus } from '../../common/hooks/use_subscription_status'; -import { createReactQueryResponse } from '../../test/fixtures/react_query'; -import { useCISIntegrationPoliciesLink } from '../../common/navigation/use_navigate_to_cis_integration_policies'; -import { useCspIntegrationLink } from '../../common/navigation/use_csp_integration_link'; -import { NO_FINDINGS_STATUS_TEST_SUBJ } from '../../components/test_subjects'; -import { render } from '@testing-library/react'; -import { expectIdsInDoc } from '../../test/utils'; -import { PACKAGE_NOT_INSTALLED_TEST_SUBJECT } from '../../components/cloud_posture_page'; -import { useLicenseManagementLocatorApi } from '../../common/api/use_license_management_locator_api'; - -jest.mock('../../common/api/use_data_view'); -jest.mock('../../common/api/use_setup_status_api'); -jest.mock('../../common/api/use_license_management_locator_api'); -jest.mock('../../common/hooks/use_subscription_status'); -jest.mock('../../common/navigation/use_navigate_to_cis_integration_policies'); -jest.mock('../../common/navigation/use_csp_integration_link'); - -const chance = new Chance(); - -beforeEach(() => { - jest.clearAllMocks(); - - (useSubscriptionStatus as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: true, - }) - ); +import { fireEvent, screen, waitFor, within } from '@testing-library/react'; +import { MemoryRouter } from '@kbn/shared-ux-router'; +import { findingsNavigation } from '../../common/navigation/constants'; +import userEvent from '@testing-library/user-event'; +import { FilterManager } from '@kbn/data-plugin/public'; +import { CspClientPluginStartDeps } from '../../types'; +import * as statusHandlers from '../../../server/routes/status/status.handlers.mock'; +import { + bsearchFindingsHandler, + generateCspFinding, + rulesGetStatesHandler, +} from './configurations.handlers.mock'; - (useLicenseManagementLocatorApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: true, - }) - ); -}); +const server = setupMockServer(); -const renderFindingsPage = () => { - render( - +const renderFindingsPage = (dependencies = getMockServerDependencies()) => { + return renderWrapper( + - + , + dependencies ); }; describe('', () => { - it('no findings state: not-deployed - shows NotDeployed instead of findings', () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { status: 'not-deployed' }, - cspm: { status: 'not-deployed' }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - }) - ); - (useCISIntegrationPoliciesLink as jest.Mock).mockImplementation(() => chance.url()); - (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + startMockServer(server); + + beforeEach(() => { + server.use(rulesGetStatesHandler); + }); + it('renders integrations installation prompt if integration is not installed', async () => { + server.use(statusHandlers.notInstalledHandler); renderFindingsPage(); - expectIdsInDoc({ - be: [NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED], - notToBe: [ - TEST_SUBJECTS.FINDINGS_CONTAINER, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, - NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, - ], - }); + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + await waitFor(() => expect(screen.getByText(/add cspm integration/i)).toBeInTheDocument()); + expect(screen.getByText(/add kspm integration/i)).toBeInTheDocument(); }); - it('no findings state: indexing - shows Indexing instead of findings', () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { status: 'indexing' }, - cspm: { status: 'indexing' }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - }) - ); - (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + it("renders the 'latest findings' DataTable component when the CSPM/KSPM integration status is 'indexed' grouped by 'none'", async () => { + const finding1 = generateCspFinding('0001', 'failed'); + const finding2 = generateCspFinding('0002', 'passed'); + server.use(statusHandlers.indexedHandler); + server.use(bsearchFindingsHandler([finding1, finding2])); renderFindingsPage(); - expectIdsInDoc({ - be: [NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING], - notToBe: [ - TEST_SUBJECTS.FINDINGS_CONTAINER, - NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, - NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, - ], - }); - }); + // Loading while checking the status API + expect(screen.getByText(/loading/i)).toBeInTheDocument(); - it('no findings state: index-timeout - shows IndexTimeout instead of findings', () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { status: 'index-timeout' }, - cspm: { status: 'index-timeout' }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - }) + await waitFor(() => + expect(screen.getByTestId('latest_findings_container')).toBeInTheDocument() ); - (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + // loading findings + await waitFor(() => expect(screen.getByText(/loading results/i)).toBeInTheDocument()); - renderFindingsPage(); + expect(screen.getByText(/2 findings/i)).toBeInTheDocument(); - expectIdsInDoc({ - be: [NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT], - notToBe: [ - TEST_SUBJECTS.FINDINGS_CONTAINER, - NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, - NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, - ], - }); + expect(screen.getByText(finding1.resource.name)).toBeInTheDocument(); + expect(screen.getByText(finding1.resource.id)).toBeInTheDocument(); + expect(screen.getByText(finding1.rule.benchmark.rule_number as string)).toBeInTheDocument(); + expect(screen.getByText(finding1.rule.name)).toBeInTheDocument(); + expect(screen.getByText(finding1.rule.section)).toBeInTheDocument(); + + expect(screen.getByText(finding2.resource.name)).toBeInTheDocument(); + expect(screen.getByText(finding2.resource.id)).toBeInTheDocument(); + expect(screen.getByText(finding2.rule.benchmark.rule_number as string)).toBeInTheDocument(); + expect(screen.getByText(finding2.rule.name)).toBeInTheDocument(); + expect(screen.getByText(finding2.rule.section)).toBeInTheDocument(); + + expect(screen.getByText(/group findings by: none/i)).toBeInTheDocument(); }); - it('no findings state: unprivileged - shows Unprivileged instead of findings', () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { status: 'unprivileged' }, - cspm: { status: 'unprivileged' }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - }) - ); - (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); + describe('SearchBar', () => { + it('set search query', async () => { + const finding1 = generateCspFinding('0001', 'failed'); + const finding2 = generateCspFinding('0002', 'passed'); - renderFindingsPage(); + server.use(statusHandlers.indexedHandler); + server.use(bsearchFindingsHandler([finding1, finding2])); + + renderFindingsPage(); + + // Loading while checking the status API + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => + expect(screen.getByTestId('latest_findings_container')).toBeInTheDocument() + ); + // loading findings + await waitFor(() => expect(screen.getByText(/loading results/i)).toBeInTheDocument()); - expectIdsInDoc({ - be: [NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED], - notToBe: [ - TEST_SUBJECTS.FINDINGS_CONTAINER, - NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, - ], + await waitFor(() => expect(screen.getByText(/2 findings/i)).toBeInTheDocument()); + + const queryInput = screen.getByTestId('queryInput'); + userEvent.paste(queryInput, `rule.section : ${finding1.rule.section}`); + + const submitButton = screen.getByTestId('querySubmitButton'); + userEvent.click(submitButton); + + await waitFor(() => expect(screen.getByText(/1 findings/i)).toBeInTheDocument()); + + expect(screen.getByText(finding1.resource.name)).toBeInTheDocument(); + expect(screen.queryByText(finding2.resource.id)).not.toBeInTheDocument(); + + userEvent.clear(queryInput); + userEvent.click(submitButton); + await waitFor(() => expect(screen.getByText(/2 findings/i)).toBeInTheDocument()); }); - }); + it('renders no results message and reset button when search query does not match', async () => { + const finding1 = generateCspFinding('0001', 'failed'); + const finding2 = generateCspFinding('0002', 'passed'); - it("renders the success state component when 'latest findings' DataView exists and request status is 'success'", async () => { - const source = await dataPluginMock.createStartContract().search.searchSource.create(); - - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => ({ - status: 'success', - data: { - kspm: { status: 'indexed' }, - cspm: { status: 'indexed' }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'not-empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], - }, - })); - (source.fetch$ as jest.Mock).mockReturnValue(of({ rawResponse: { hits: { hits: [] } } })); - - (useDataView as jest.Mock).mockReturnValue({ - status: 'success', - data: createStubDataView({ - spec: { - id: CSP_LATEST_FINDINGS_DATA_VIEW, - }, - }), - } as UseQueryResult); + server.use(statusHandlers.indexedHandler); + server.use(bsearchFindingsHandler([finding1, finding2])); - renderFindingsPage(); + renderFindingsPage(); - expectIdsInDoc({ - be: [TEST_SUBJECTS.LATEST_FINDINGS_CONTAINER], - notToBe: [ - NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, - NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, - NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, - ], + // Loading while checking the status API + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => + expect(screen.getByTestId('latest_findings_container')).toBeInTheDocument() + ); + // loading findings + await waitFor(() => expect(screen.getByText(/loading results/i)).toBeInTheDocument()); + + await waitFor(() => expect(screen.getByText(/2 findings/i)).toBeInTheDocument()); + + const queryInput = screen.getByTestId('queryInput'); + userEvent.paste(queryInput, `rule.section : Invalid`); + + const submitButton = screen.getByTestId('querySubmitButton'); + userEvent.click(submitButton); + + await waitFor(() => + expect(screen.getByText(/no results match your search criteria/i)).toBeInTheDocument() + ); + + const resetButton = screen.getByRole('button', { + name: /reset filters/i, + }); + + userEvent.click(resetButton); + await waitFor(() => expect(screen.getByText(/2 findings/i)).toBeInTheDocument()); }); - }); + it('add filter', async () => { + const finding1 = generateCspFinding('0001', 'failed'); + const finding2 = generateCspFinding('0002', 'passed'); - it('renders integrations installation prompt if integration is not installed', async () => { - (useCspSetupStatusApi as jest.Mock).mockImplementation(() => - createReactQueryResponse({ - status: 'success', - data: { - kspm: { status: 'not-installed' }, - cspm: { status: 'not-installed' }, - indicesDetails: [ - { index: 'logs-cloud_security_posture.findings_latest-default', status: 'empty' }, - { index: 'logs-cloud_security_posture.findings-default*', status: 'empty' }, - ], + server.use(statusHandlers.indexedHandler); + server.use(bsearchFindingsHandler([finding1, finding2])); + + renderFindingsPage(); + + // Loading while checking the status API + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => + expect(screen.getByTestId('latest_findings_container')).toBeInTheDocument() + ); + // loading findings + await waitFor(() => expect(screen.getByText(/loading results/i)).toBeInTheDocument()); + + await waitFor(() => expect(screen.getByText(/2 findings/i)).toBeInTheDocument()); + + userEvent.click(screen.getByTestId('addFilter'), undefined, { skipPointerEventsCheck: true }); + + await waitFor(() => + expect(screen.getByTestId('filterFieldSuggestionList')).toBeInTheDocument() + ); + + const filterFieldSuggestionListInput = within( + screen.getByTestId('filterFieldSuggestionList') + ).getByTestId('comboBoxSearchInput'); + + userEvent.paste(filterFieldSuggestionListInput, 'rule.section'); + userEvent.keyboard('{enter}'); + + const filterOperatorListInput = within(screen.getByTestId('filterOperatorList')).getByTestId( + 'comboBoxSearchInput' + ); + userEvent.click(filterOperatorListInput, undefined, { skipPointerEventsCheck: true }); + + const filterOption = within( + screen.getByTestId('comboBoxOptionsList filterOperatorList-optionsList') + ).getByRole('option', { name: 'is' }); + fireEvent.click(filterOption); + + const filterParamsInput = within(screen.getByTestId('filterParams')).getByRole('textbox'); + userEvent.paste(filterParamsInput, finding1.rule.section); + + userEvent.click(screen.getByTestId('saveFilter'), undefined, { + skipPointerEventsCheck: true, + }); + + await waitFor(() => expect(screen.getByText(/1 findings/i)).toBeInTheDocument()); + expect(screen.getByText(finding1.resource.name)).toBeInTheDocument(); + expect(screen.queryByText(finding2.resource.id)).not.toBeInTheDocument(); + }, 10000); + it('remove filter', async () => { + const finding1 = generateCspFinding('0001', 'failed'); + const finding2 = generateCspFinding('0002', 'passed'); + + const mockedFilterManager = new FilterManager(getMockServerDependencies().core.uiSettings); + mockedFilterManager.setFilters([ + { + meta: { + alias: `rule.section: ${finding1.rule.section}`, + negate: false, + disabled: false, + key: 'rule.section', + value: finding1.rule.section, + }, + query: { + match_phrase: { + 'rule.section': finding1.rule.section, + }, + }, }, - }) - ); - (useCspIntegrationLink as jest.Mock).mockImplementation(() => chance.url()); - renderFindingsPage(); + ]); + const mockDependenciesWithFilter = { + ...getMockServerDependencies(), + deps: { + ...getMockServerDependencies().deps, + data: { + ...getMockServerDependencies().deps.data, + query: { + ...getMockServerDependencies().deps.data!.query, + filterManager: mockedFilterManager, + }, + }, + } as unknown as Partial, + }; + + server.use(statusHandlers.indexedHandler); + server.use(bsearchFindingsHandler([finding1, finding2])); + + renderFindingsPage(mockDependenciesWithFilter); + + // Loading while checking the status API + expect(screen.getByText(/loading/i)).toBeInTheDocument(); + + await waitFor(() => + expect(screen.getByTestId('latest_findings_container')).toBeInTheDocument() + ); + // loading findings + await waitFor(() => expect(screen.getByText(/loading results/i)).toBeInTheDocument()); + + await waitFor(() => expect(screen.getByText(/1 findings/i)).toBeInTheDocument()); + expect(screen.getByText(finding1.resource.name)).toBeInTheDocument(); + expect(screen.queryByText(finding2.resource.id)).not.toBeInTheDocument(); + + const deleteFilter = screen.getByRole('button', { + name: `Delete rule.section: ${finding1.rule.section}`, + }); + userEvent.click(deleteFilter); + + await waitFor(() => expect(screen.getByText(/2 findings/i)).toBeInTheDocument()); - expectIdsInDoc({ - be: [PACKAGE_NOT_INSTALLED_TEST_SUBJECT], - notToBe: [ - TEST_SUBJECTS.LATEST_FINDINGS_CONTAINER, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEX_TIMEOUT, - NO_FINDINGS_STATUS_TEST_SUBJ.NO_AGENTS_DEPLOYED, - NO_FINDINGS_STATUS_TEST_SUBJ.INDEXING, - NO_FINDINGS_STATUS_TEST_SUBJ.UNPRIVILEGED, - ], + expect(screen.getByText(finding1.resource.name)).toBeInTheDocument(); + expect(screen.getByText(finding2.resource.name)).toBeInTheDocument(); }); }); }); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx index 1452bc60c3bf2..1c94500579e48 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/configurations.tsx @@ -11,7 +11,7 @@ import { TrackApplicationView } from '@kbn/usage-collection-plugin/public'; import { LATEST_FINDINGS_INDEX_PATTERN } from '../../../common/constants'; import { useCspSetupStatusApi } from '../../common/api/use_setup_status_api'; import { NoFindingsStates } from '../../components/no_findings_states'; -import { CloudPosturePage } from '../../components/cloud_posture_page'; +import { CloudPosturePage, defaultLoadingRenderer } from '../../components/cloud_posture_page'; import { useDataView } from '../../common/api/use_data_view'; import { cloudPosturePages, findingsNavigation } from '../../common/navigation/constants'; import { LatestFindingsContainer } from './latest_findings/latest_findings_container'; @@ -20,7 +20,7 @@ import { DataViewContext } from '../../common/contexts/data_view_context'; export const Configurations = () => { const location = useLocation(); const dataViewQuery = useDataView(LATEST_FINDINGS_INDEX_PATTERN); - const { data: getSetupStatus } = useCspSetupStatusApi(); + const { data: getSetupStatus, isLoading: getSetupStatusIsLoading } = useCspSetupStatusApi(); const hasConfigurationFindings = getSetupStatus?.kspm.status === 'indexed' || getSetupStatus?.cspm.status === 'indexed'; @@ -29,6 +29,7 @@ export const Configurations = () => { const noFindingsForPostureType = getSetupStatus?.cspm.status !== 'not-installed' ? 'cspm' : 'kspm'; + if (getSetupStatusIsLoading) return defaultLoadingRenderer(); if (!hasConfigurationFindings) return ; const dataViewContextValue = { diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_container.tsx index e1580d9c87848..cfb572116e65c 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/latest_findings_container.tsx @@ -75,7 +75,7 @@ const SubGrouping = ({ }; export const LatestFindingsContainer = () => { - const { grouping, isFetching, setUrlQuery, onResetFilters, error, isEmptyResults } = + const { grouping, isFetching, urlQuery, setUrlQuery, onResetFilters, error, isEmptyResults } = useLatestFindingsGrouping({ groupPanelRenderer, groupStatsRenderer }); const renderChildComponent = ({ @@ -145,7 +145,7 @@ export const LatestFindingsContainer = () => { if (error || isEmptyResults) { return ( <> - + {error && } {isEmptyResults && } @@ -155,7 +155,7 @@ export const LatestFindingsContainer = () => { return ( <> - +
{renderChildComponent({ level: 0, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx index 802ed52be9228..47f00a9a1927a 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/latest_findings/use_latest_findings_grouping.tsx @@ -150,6 +150,7 @@ export const useLatestFindingsGrouping = ({ query, onChangeGroupsItemsPerPage, onChangeGroupsPage, + urlQuery, setUrlQuery, uniqueValue, isNoneSelected, @@ -261,6 +262,7 @@ export const useLatestFindingsGrouping = ({ selectedGroup, onChangeGroupsItemsPerPage, onChangeGroupsPage, + urlQuery, setUrlQuery, isGroupSelected: !isNoneSelected, isGroupLoading: !data, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_search_bar.tsx b/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_search_bar.tsx index 43077778c4fdf..755ecb86c73ba 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_search_bar.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/configurations/layout/findings_search_bar.tsx @@ -22,10 +22,12 @@ interface FindingsSearchBarProps { setQuery(v: Partial): void; loading: boolean; placeholder?: string; + query: SearchBarQueryProps; } export const FindingsSearchBar = ({ loading, + query, setQuery, placeholder = i18n.translate('xpack.csp.findings.searchBar.searchPlaceholder', { defaultMessage: 'Search findings (eg. rule.section : "API Server" )', @@ -55,6 +57,11 @@ export const FindingsSearchBar = ({ onQuerySubmit={setQuery} onFiltersUpdated={(value: Filter[]) => setQuery({ filters: value })} placeholder={placeholder} + query={{ + query: query?.query?.query || '', + language: query?.query?.language || 'kuery', + }} + filters={query?.filters || []} />
); diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_grouping.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_grouping.tsx index fa90d4f6209bd..2e1c93f4218f4 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_grouping.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/hooks/use_latest_vulnerabilities_grouping.tsx @@ -129,6 +129,7 @@ export const useLatestVulnerabilitiesGrouping = ({ query, onChangeGroupsItemsPerPage, onChangeGroupsPage, + urlQuery, setUrlQuery, uniqueValue, isNoneSelected, @@ -194,6 +195,7 @@ export const useLatestVulnerabilitiesGrouping = ({ selectedGroup, onChangeGroupsItemsPerPage, onChangeGroupsPage, + urlQuery, setUrlQuery, isGroupSelected: !isNoneSelected, isGroupLoading: !data, diff --git a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/latest_vulnerabilities_container.tsx b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/latest_vulnerabilities_container.tsx index 4a33228e00bab..6b2ed7aea04db 100644 --- a/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/latest_vulnerabilities_container.tsx +++ b/x-pack/plugins/cloud_security_posture/public/pages/vulnerabilities/latest_vulnerabilities_container.tsx @@ -137,13 +137,13 @@ export const LatestVulnerabilitiesContainer = () => { ); }; - const { grouping, isFetching, setUrlQuery, onResetFilters, error, isEmptyResults } = + const { grouping, isFetching, urlQuery, setUrlQuery, onResetFilters, error, isEmptyResults } = useLatestVulnerabilitiesGrouping({ groupPanelRenderer, groupStatsRenderer }); if (error || isEmptyResults) { return ( <> - + {error && } {isEmptyResults && } @@ -152,7 +152,7 @@ export const LatestVulnerabilitiesContainer = () => { } return ( <> - +
{renderChildComponent({ diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/dataview.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/dataview.handlers.mock.ts new file mode 100644 index 0000000000000..266f7f652d299 --- /dev/null +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/dataview.handlers.mock.ts @@ -0,0 +1,47 @@ +/* + * 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 { http, HttpResponse } from 'msw'; + +const generateDataViewField = (name: string, type: 'string' | 'date' = 'string') => ({ + name, + type, + esTypes: [type === 'string' ? 'keyword' : 'date'], + searchable: true, + aggregatable: true, + readFromDocValues: true, + metadata_field: false, +}); + +export const defaultDataViewFindHandler = http.get( + 'http://localhost/internal/data_views/fields', + ({ request }) => { + const url = new URL(request.url); + const pattern = url.searchParams.get('pattern'); + + if (pattern === 'logs-cloud_security_posture.findings_latest-*') { + return HttpResponse.json({ + fields: [ + generateDataViewField('@timestamp', 'date'), + generateDataViewField('resource.id'), + generateDataViewField('resource.name'), + generateDataViewField('resource.sub_type'), + generateDataViewField('result.evaluation'), + generateDataViewField('rule.benchmark.rule_number'), + generateDataViewField('rule.name'), + generateDataViewField('rule.section'), + ], + indices: ['logs-cloud_security_posture.findings_latest-default'], + }); + } + + return HttpResponse.json({ + fields: [], + indices: [], + }); + } +); diff --git a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.handlers.mock.ts b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/fleet.handlers.mock.ts similarity index 89% rename from x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.handlers.mock.ts rename to x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/fleet.handlers.mock.ts index 904083ca86f5c..01065b3339455 100644 --- a/x-pack/plugins/cloud_security_posture/public/components/no_findings_states/no_findings_states.handlers.mock.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/fleet.handlers.mock.ts @@ -7,7 +7,7 @@ import { http, HttpResponse } from 'msw'; -export const fleetCspPackageHandler = http.get( +export const defaultFleetCspPackageHandler = http.get( `/api/fleet/epm/packages/cloud_security_posture`, () => { return HttpResponse.json({ diff --git a/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/index.ts b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/index.ts index 91eb25630b222..311e3ba1b7a27 100644 --- a/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/index.ts +++ b/x-pack/plugins/cloud_security_posture/public/test/mock_server/handlers/index.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { defaultDataViewFindHandler } from './dataview.handlers.mock'; +import { defaultFleetCspPackageHandler } from './fleet.handlers.mock'; import { defaultApiLicensingInfo } from './licensing.handlers.mock'; /** @@ -12,4 +14,8 @@ import { defaultApiLicensingInfo } from './licensing.handlers.mock'; * when the mock server is started, but can be overridden by specific tests when needed. * Recommended to use these handlers for common endpoints. */ -export const defaultHandlers = [defaultApiLicensingInfo]; +export const defaultHandlers = [ + defaultApiLicensingInfo, + defaultDataViewFindHandler, + defaultFleetCspPackageHandler, +]; diff --git a/x-pack/test/cloud_security_posture_functional/pages/findings.ts b/x-pack/test/cloud_security_posture_functional/pages/findings.ts index 841799dd115f6..57b9f303a2046 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/findings.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/findings.ts @@ -17,7 +17,6 @@ import type { FtrProviderContext } from '../ftr_provider_context'; // eslint-disable-next-line import/no-default-export export default function ({ getPageObjects, getService }: FtrProviderContext) { - const queryBar = getService('queryBar'); const filterBar = getService('filterBar'); const testSubjects = getService('testSubjects'); const retry = getService('retry'); @@ -100,9 +99,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { }, ]; - const ruleName1 = data[0].rule.name; - const ruleName2 = data[1].rule.name; - const getCspBenchmarkRules = async (benchmarkId: string): Promise => { const cspBenchmarkRules = await kibanaServer.savedObjects.find({ type: CSP_BENCHMARK_RULE_SAVED_OBJECT_TYPE, @@ -151,37 +147,6 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await findings.index.remove(); }); - // FLAKY: https://github.com/elastic/kibana/issues/174472 - describe.skip('SearchBar', () => { - it('add filter', async () => { - // Filter bar uses the field's customLabel in the DataView - await filterBar.addFilter({ field: 'Rule Name', operation: 'is', value: ruleName1 }); - - expect(await filterBar.hasFilter('rule.name', ruleName1)).to.be(true); - expect(await latestFindingsTable.hasColumnValue('rule.name', ruleName1)).to.be(true); - }); - - it('remove filter', async () => { - await filterBar.removeFilter('rule.name'); - - expect(await filterBar.hasFilter('rule.name', ruleName1)).to.be(false); - expect(await latestFindingsTable.getRowsCount()).to.be(data.length); - }); - - it('set search query', async () => { - await queryBar.setQuery(ruleName1); - await queryBar.submitQuery(); - - expect(await latestFindingsTable.hasColumnValue('rule.name', ruleName1)).to.be(true); - expect(await latestFindingsTable.hasColumnValue('rule.name', ruleName2)).to.be(false); - - await queryBar.setQuery(''); - await queryBar.submitQuery(); - - expect(await latestFindingsTable.getRowsCount()).to.be(data.length); - }); - }); - // FLAKY: https://github.com/elastic/kibana/issues/152913 describe.skip('Table Sort', () => { type SortingMethod = (a: string, b: string) => number; From 606c6958664b30805a022b3a46e01f38c466f611 Mon Sep 17 00:00:00 2001 From: Cee Chen <549407+cee-chen@users.noreply.github.com> Date: Tue, 25 Jun 2024 09:02:58 -0700 Subject: [PATCH 09/22] Convert `styled-component` usage to Emotion vanilla CSS (#186849) ## Summary Follow up to https://github.com/elastic/kibana/pull/186324/commits/9125e17a7f1f042e1f0a18b9788ba19f9285ff70 - move away from using `euiStyled` (which throws errors if plugin(s) using the component aren't wrapped in `KibanaStyledComponentsThemeProvider`. See EUI's Emotion FAQ for more information: https://github.com/elastic/eui/discussions/6828 ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - ~[ ] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/))~ - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --- .../action_notify_when.tsx | 29 ++++++++++++------- .../action_type_form.test.tsx | 29 +++++++++---------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_notify_when.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_notify_when.tsx index c1a34bdd146e5..ce9ddfcad2be1 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_notify_when.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_notify_when.tsx @@ -7,9 +7,9 @@ import { RuleAction, RuleNotifyWhen } from '@kbn/alerting-plugin/common'; import React, { useState, useEffect, useCallback, useMemo } from 'react'; +import { css } from '@emotion/css'; // We can't use @emotion/react - this component gets used with plugins that use both styled-components and Emotion import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { euiStyled } from '@kbn/kibana-react-plugin/common'; import { EuiFlexGroup, EuiFlexItem, @@ -23,6 +23,7 @@ import { EuiButtonEmpty, EuiContextMenuPanel, EuiContextMenuItem, + useEuiTheme, } from '@elastic/eui'; import { some, filter, map } from 'fp-ts/lib/Option'; import { pipe } from 'fp-ts/lib/pipeable'; @@ -242,28 +243,39 @@ export const ActionNotifyWhen = ({ [onSummaryChange, selectedOptionDoesNotExist, onNotifyWhenChange, getDefaultNotifyWhenOption] ); + const { euiTheme } = useEuiTheme(); + const summaryContextMenuOptionStyles = useMemo( + () => css` + min-width: 300px; + padding: ${euiTheme.size.s}; + `, + [euiTheme] + ); + const summaryOptions = useMemo( () => [ - selectSummaryOption(true)} icon={frequency.summary ? 'check' : 'empty'} id="actionNotifyWhen-option-summary" data-test-subj="actionNotifyWhen-option-summary" + className={summaryContextMenuOptionStyles} > {SUMMARY_OF_ALERTS} - , - , + selectSummaryOption(false)} icon={!frequency.summary ? 'check' : 'empty'} id="actionNotifyWhen-option-for_each" data-test-subj="actionNotifyWhen-option-for_each" + className={summaryContextMenuOptionStyles} > {FOR_EACH_ALERT} - , + , ], - [frequency.summary, selectSummaryOption] + [frequency.summary, selectSummaryOption, summaryContextMenuOptionStyles] ); const summaryOrPerRuleSelect = ( @@ -387,8 +399,3 @@ const SUMMARY_OF_ALERTS = i18n.translate( 'xpack.triggersActionsUI.sections.ruleForm.actionNotifyWhen.summaryOption', { defaultMessage: 'Summary of alerts' } ); - -const SummaryContextMenuOption = euiStyled(EuiContextMenuItem)` - min-width: 300px; - padding: ${({ theme }) => theme.eui.euiSizeS}; -`; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx index 0a71603a5b55a..cbf6c17e78481 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.test.tsx @@ -18,7 +18,6 @@ import { } from '../../../types'; import { act } from 'react-dom/test-utils'; import { EuiFieldText } from '@elastic/eui'; -import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { I18nProvider, __IntlProvider as IntlProvider } from '@kbn/i18n-react'; import { render, waitFor, screen } from '@testing-library/react'; import { DEFAULT_FREQUENCY } from '../../../common/constants'; @@ -414,21 +413,19 @@ describe('action_type_form', () => { frequency: DEFAULT_FREQUENCY, }; const wrapper = render( - - - {getActionTypeForm({ - index: 1, - actionItem, - setActionFrequencyProperty: () => { - actionItem.frequency = { - notifyWhen: RuleNotifyWhen.ACTIVE, - throttle: null, - summary: true, - }; - }, - })} - - + + {getActionTypeForm({ + index: 1, + actionItem, + setActionFrequencyProperty: () => { + actionItem.frequency = { + notifyWhen: RuleNotifyWhen.ACTIVE, + throttle: null, + summary: true, + }; + }, + })} + ); const summaryOrPerRuleSelect = wrapper.getByTestId('summaryOrPerRuleSelect'); From 7ce69fc52c505b06093559ac5ebb83f3d1db757e Mon Sep 17 00:00:00 2001 From: Tomasz Ciecierski Date: Tue, 25 Jun 2024 18:44:27 +0200 Subject: [PATCH 10/22] [EDR Workflows] Complete Crowdstrike actions (#186522) --- .../crowdstrike_actions_client.test.ts | 202 +++++++++++++----- .../crowdstrike/crowdstrike_actions_client.ts | 83 ++++--- .../crowdstrike_agent_status_client.ts | 2 +- 3 files changed, 184 insertions(+), 103 deletions(-) diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.test.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.test.ts index 99274f83240c2..fd1f597cf3ef1 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.test.ts @@ -13,9 +13,13 @@ import { ResponseActionsNotSupportedError } from '../errors'; import type { CrowdstrikeActionsClientOptionsMock } from './mocks'; import { CrowdstrikeMock } from './mocks'; -import { ENDPOINT_ACTIONS_INDEX } from '../../../../../../common/endpoint/constants'; +import { + ENDPOINT_ACTION_RESPONSES_INDEX, + ENDPOINT_ACTIONS_INDEX, +} from '../../../../../../common/endpoint/constants'; import { SUB_ACTION } from '@kbn/stack-connectors-plugin/common/crowdstrike/constants'; import type { NormalizedExternalConnectorClient } from '../../..'; + jest.mock('../../action_details_by_id', () => { const originalMod = jest.requireActual('../../action_details_by_id'); @@ -75,6 +79,48 @@ describe('CrowdstrikeActionsClient class', () => { }); }); + it('should save response with error in case of actionResponse containing errors', async () => { + // mock execute of CS action to return error + const actionResponse = { + data: { + errors: [{ message: 'error message' }], + }, + }; + (connectorActionsMock.execute as jest.Mock).mockResolvedValueOnce(actionResponse); + + await crowdstrikeActionsClient.isolate( + createCrowdstrikeIsolationOptions({ actionId: '123-345-567' }) + ); + expect(classConstructorOptions.esClient.index.mock.calls[1][0]).toEqual({ + document: { + '@timestamp': expect.any(String), + agent: { id: ['1-2-3'] }, + EndpointActions: { + action_id: expect.any(String), + completed_at: expect.any(String), + started_at: expect.any(String), + data: { + command: 'isolate', + comment: 'test comment', + hosts: { + '1-2-3': { + name: 'Crowdstrike-1460', + }, + }, + }, + input_type: 'crowdstrike', + }, + error: { + code: '500', + message: 'Crowdstrike action failed: error message', + }, + meta: undefined, + }, + index: ENDPOINT_ACTION_RESPONSES_INDEX, + refresh: 'wait_for', + }); + }); + describe(`#isolate()`, () => { it('should send action to Crowdstrike', async () => { await crowdstrikeActionsClient.isolate( @@ -99,40 +145,61 @@ describe('CrowdstrikeActionsClient class', () => { it('should write action request to endpoint indexes', async () => { await crowdstrikeActionsClient.isolate(createCrowdstrikeIsolationOptions()); - // we do not write response to es yet - expect(classConstructorOptions.esClient.index).toHaveBeenCalledTimes(1); - expect(classConstructorOptions.esClient.index).toHaveBeenNthCalledWith( - 1, - { - document: { - '@timestamp': expect.any(String), - EndpointActions: { - action_id: expect.any(String), - data: { - command: 'isolate', - comment: 'test comment', - parameters: undefined, - hosts: { - '1-2-3': { - name: 'Crowdstrike-1460', - }, + expect(classConstructorOptions.esClient.index).toHaveBeenCalledTimes(2); + expect(classConstructorOptions.esClient.index.mock.calls[0][0]).toEqual({ + document: { + '@timestamp': expect.any(String), + EndpointActions: { + action_id: expect.any(String), + data: { + command: 'isolate', + comment: 'test comment', + parameters: undefined, + hosts: { + '1-2-3': { + name: 'Crowdstrike-1460', }, }, - expiration: expect.any(String), - input_type: 'crowdstrike', - type: 'INPUT_ACTION', }, - agent: { id: ['1-2-3'] }, - meta: { - hostName: 'Crowdstrike-1460', + expiration: expect.any(String), + input_type: 'crowdstrike', + type: 'INPUT_ACTION', + }, + agent: { id: ['1-2-3'] }, + meta: { + hostName: 'Crowdstrike-1460', + }, + user: { id: 'foo' }, + }, + index: ENDPOINT_ACTIONS_INDEX, + refresh: 'wait_for', + }); + expect(classConstructorOptions.esClient.index.mock.calls[1][0]).toEqual({ + document: { + '@timestamp': expect.any(String), + agent: { id: ['1-2-3'] }, + EndpointActions: { + action_id: expect.any(String), + completed_at: expect.any(String), + started_at: expect.any(String), + data: { + command: 'isolate', + comment: 'test comment', + hosts: { + '1-2-3': { + name: 'Crowdstrike-1460', + }, + parameters: undefined, + }, }, - user: { id: 'foo' }, + input_type: 'crowdstrike', + error: undefined, + meta: undefined, }, - index: ENDPOINT_ACTIONS_INDEX, - refresh: 'wait_for', }, - { meta: true } - ); + index: ENDPOINT_ACTION_RESPONSES_INDEX, + refresh: 'wait_for', + }); }); it('should return action details', async () => { @@ -174,40 +241,61 @@ describe('CrowdstrikeActionsClient class', () => { it('should write action request to endpoint indexes', async () => { await crowdstrikeActionsClient.release(createCrowdstrikeIsolationOptions()); - // we do not write response to es yet - expect(classConstructorOptions.esClient.index).toHaveBeenCalledTimes(1); - expect(classConstructorOptions.esClient.index).toHaveBeenNthCalledWith( - 1, - { - document: { - '@timestamp': expect.any(String), - EndpointActions: { - action_id: expect.any(String), - data: { - command: 'unisolate', - comment: 'test comment', - parameters: undefined, - hosts: { - '1-2-3': { - name: 'Crowdstrike-1460', - }, + expect(classConstructorOptions.esClient.index).toHaveBeenCalledTimes(2); + expect(classConstructorOptions.esClient.index.mock.calls[0][0]).toEqual({ + document: { + '@timestamp': expect.any(String), + EndpointActions: { + action_id: expect.any(String), + data: { + command: 'unisolate', + comment: 'test comment', + parameters: undefined, + hosts: { + '1-2-3': { + name: 'Crowdstrike-1460', }, }, - expiration: expect.any(String), - input_type: 'crowdstrike', - type: 'INPUT_ACTION', }, - agent: { id: ['1-2-3'] }, - meta: { - hostName: 'Crowdstrike-1460', + expiration: expect.any(String), + input_type: 'crowdstrike', + type: 'INPUT_ACTION', + }, + agent: { id: ['1-2-3'] }, + meta: { + hostName: 'Crowdstrike-1460', + }, + user: { id: 'foo' }, + }, + index: ENDPOINT_ACTIONS_INDEX, + refresh: 'wait_for', + }); + expect(classConstructorOptions.esClient.index.mock.calls[1][0]).toEqual({ + document: { + '@timestamp': expect.any(String), + agent: { id: ['1-2-3'] }, + EndpointActions: { + action_id: expect.any(String), + completed_at: expect.any(String), + started_at: expect.any(String), + data: { + command: 'unisolate', + comment: 'test comment', + hosts: { + '1-2-3': { + name: 'Crowdstrike-1460', + }, + }, + parameters: undefined, }, - user: { id: 'foo' }, + input_type: 'crowdstrike', }, - index: ENDPOINT_ACTIONS_INDEX, - refresh: 'wait_for', + error: undefined, + meta: undefined, }, - { meta: true } - ); + index: ENDPOINT_ACTION_RESPONSES_INDEX, + refresh: 'wait_for', + }); }); it('should return action details', async () => { diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts index ac982f43f151f..b4b11610e5c02 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions/clients/crowdstrike/crowdstrike_actions_client.ts @@ -11,6 +11,7 @@ import { CROWDSTRIKE_CONNECTOR_ID, } from '@kbn/stack-connectors-plugin/common/crowdstrike/constants'; import type { SearchResponse } from '@elastic/elasticsearch/lib/api/types'; +import type { CrowdstrikeBaseApiResponse } from '@kbn/stack-connectors-plugin/common/crowdstrike/types'; import type { CrowdstrikeActionRequestCommonMeta } from '../../../../../../common/endpoint/types/crowdstrike'; import type { CommonResponseActionMethodOptions, @@ -159,45 +160,6 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { } } - // TODO TC: uncomment when working on agent status support - // private async getAgentDetails( - // id: string - // ): Promise { - // const executeOptions: NormalizedExternalConnectorClientExecuteOptions< - // CrowdstrikeGetAgentsParams, - // SUB_ACTION - // > = { - // params: { - // subAction: SUB_ACTION.GET_AGENT_DETAILS, - // subActionParams: { - // ids: [id], - // }, - // }, - // }; - - // let crowdstrikeApiResponse: CrowdstrikeGetAgentsResponse | undefined; - - // try { - // const response = await this.connectorActionsClient.execute(executeOptions); - - // this.log.debug(`Response for Crowdstrike agent id [${id}] returned:\n${stringify(response)}`); - - // crowdstrikeApiResponse = response.data; - // } catch (err) { - // throw new ResponseActionsClientError( - // `Error while attempting to retrieve Crowdstrike host with agent id [${id}]`, - // 500, - // err - // ); - // } - - // if (!crowdstrikeApiResponse || !crowdstrikeApiResponse.resources[0]) { - // throw new ResponseActionsClientError(`Crowdstrike agent id [${id}] not found`, 404); - // } - - // return crowdstrikeApiResponse.resources[0]; - // } - protected async validateRequest( payload: ResponseActionsClientWriteActionRequestToEndpointIndexOptions ): Promise { @@ -224,17 +186,16 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { ...this.getMethodOptions(options), command: 'isolate', }; - + let actionResponse: ActionTypeExecutorResult | undefined; if (!reqIndexOptions.error) { let error = (await this.validateRequest(reqIndexOptions)).error; const actionCommentMessage = ELASTIC_RESPONSE_ACTION_MESSAGE( this.options.username, reqIndexOptions.actionId ); - if (!error) { try { - await this.sendAction(SUB_ACTION.HOST_ACTIONS, { + actionResponse = (await this.sendAction(SUB_ACTION.HOST_ACTIONS, { ids: actionRequest.endpoint_ids, actionParameters: { comment: reqIndexOptions.comment @@ -242,7 +203,7 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { : actionCommentMessage, }, command: 'contain', - }); + })) as ActionTypeExecutorResult; } catch (err) { error = err; } @@ -257,6 +218,11 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { const actionRequestDoc = await this.writeActionRequestToEndpointIndex(reqIndexOptions); + // Ensure actionResponse is assigned before using it + if (actionResponse) { + await this.completeCrowdstrikeAction(actionResponse, actionRequestDoc); + } + await this.updateCases({ command: reqIndexOptions.command, caseIds: reqIndexOptions.case_ids, @@ -284,6 +250,7 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { command: 'unisolate', }; + let actionResponse: ActionTypeExecutorResult | undefined; if (!reqIndexOptions.error) { let error = (await this.validateRequest(reqIndexOptions)).error; const actionCommentMessage = ELASTIC_RESPONSE_ACTION_MESSAGE( @@ -292,13 +259,13 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { ); if (!error) { try { - await this.sendAction(SUB_ACTION.HOST_ACTIONS, { + actionResponse = (await this.sendAction(SUB_ACTION.HOST_ACTIONS, { ids: actionRequest.endpoint_ids, command: 'lift_containment', comment: reqIndexOptions.comment ? `${actionCommentMessage}: ${reqIndexOptions.comment}` : actionCommentMessage, - }); + })) as ActionTypeExecutorResult; } catch (err) { error = err; } @@ -313,6 +280,11 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { const actionRequestDoc = await this.writeActionRequestToEndpointIndex(reqIndexOptions); + // Ensure actionResponse is assigned before using it + if (actionResponse) { + await this.completeCrowdstrikeAction(actionResponse, actionRequestDoc); + } + await this.updateCases({ command: reqIndexOptions.command, caseIds: reqIndexOptions.case_ids, @@ -330,6 +302,27 @@ export class CrowdstrikeActionsClient extends ResponseActionsClientImpl { return this.fetchActionDetails(actionRequestDoc.EndpointActions.action_id); } + private async completeCrowdstrikeAction( + actionResponse: ActionTypeExecutorResult | undefined, + doc: LogsEndpointAction + ): Promise { + const options = { + actionId: doc.EndpointActions.action_id, + agentId: doc.agent.id, + data: doc.EndpointActions.data, + ...(actionResponse?.data?.errors?.length + ? { + error: { + code: '500', + message: `Crowdstrike action failed: ${actionResponse.data.errors[0].message}`, + }, + } + : {}), + }; + + await this.writeActionResponseToEndpointIndex(options); + } + async processPendingActions({ abortSignal, addToQueue, diff --git a/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.ts index 61d0ae9a7ef5e..61f746dbf4e55 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/agent/clients/crowdstrike/crowdstrike_agent_status_client.ts @@ -135,7 +135,7 @@ export class CrowdstrikeAgentStatusClient extends AgentStatusClient { const agentStatuses = await this.getAgentStatusFromConnectorAction(agentIds); return agentIds.reduce((acc, agentId) => { - const agentInfo = mostRecentAgentInfosByAgentId[agentId].crowdstrike; + const agentInfo = mostRecentAgentInfosByAgentId[agentId]?.crowdstrike; const agentStatus = agentStatuses[agentId]; const pendingActions = allPendingActions.find( From d5b0ddda62205031696befed213d6abb2f4e0569 Mon Sep 17 00:00:00 2001 From: Philippe Oberti Date: Tue, 25 Jun 2024 12:37:20 -0500 Subject: [PATCH 11/22] [Security Solution][Notes] - add delete note to flyout notes tab (#186843) --- .../public/common/mock/global_state.ts | 2 + .../left/components/add_note.test.tsx | 31 +++- .../left/components/notes_list.test.tsx | 139 ++++++++++++++++-- .../left/components/notes_list.tsx | 65 +++++++- .../left/components/test_ids.ts | 1 + .../security_solution/public/notes/api/api.ts | 11 ++ .../public/notes/store/notes.slice.test.ts | 118 +++++++++++++-- .../public/notes/store/notes.slice.ts | 29 ++++ 8 files changed, 354 insertions(+), 42 deletions(-) diff --git a/x-pack/plugins/security_solution/public/common/mock/global_state.ts b/x-pack/plugins/security_solution/public/common/mock/global_state.ts index 7a865a4be9f04..4365a30c2f07d 100644 --- a/x-pack/plugins/security_solution/public/common/mock/global_state.ts +++ b/x-pack/plugins/security_solution/public/common/mock/global_state.ts @@ -521,10 +521,12 @@ export const mockGlobalState: State = { status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Idle, }, error: { fetchNotesByDocumentId: null, createNote: null, + deleteNote: null, }, }, }; diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.test.tsx index 95e6591dec9cb..e4c5264b249b5 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/add_note.test.tsx @@ -52,9 +52,16 @@ describe('AddNote', () => { }); it('should render the add note button in loading state while creating a new note', () => { - const state = { ...mockGlobalState }; - state.notes.status.createNote = ReqStatus.Loading; - const store = createMockStore(state); + const store = createMockStore({ + ...mockGlobalState, + notes: { + ...mockGlobalState.notes, + status: { + ...mockGlobalState.notes.status, + createNote: ReqStatus.Loading, + }, + }, + }); const { container } = render( @@ -66,10 +73,20 @@ describe('AddNote', () => { }); it('should render error toast if create a note fails', () => { - const state = { ...mockGlobalState }; - state.notes.status.createNote = ReqStatus.Failed; - state.notes.error.createNote = { type: 'http', status: 500 }; - const store = createMockStore(state); + const store = createMockStore({ + ...mockGlobalState, + notes: { + ...mockGlobalState.notes, + status: { + ...mockGlobalState.notes.status, + createNote: ReqStatus.Failed, + }, + error: { + ...mockGlobalState.notes.error, + createNote: { type: 'http', status: 500 }, + }, + }, + }); render( diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.test.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.test.tsx index 82dfeac7e60ad..5f561d34f15d9 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.test.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.test.tsx @@ -7,9 +7,14 @@ import { render } from '@testing-library/react'; import React from 'react'; -import { ADD_NOTE_LOADING_TEST_ID, NOTES_COMMENT_TEST_ID, NOTES_LOADING_TEST_ID } from './test_ids'; +import { + ADD_NOTE_LOADING_TEST_ID, + DELETE_NOTE_BUTTON_TEST_ID, + NOTES_COMMENT_TEST_ID, + NOTES_LOADING_TEST_ID, +} from './test_ids'; import { createMockStore, mockGlobalState, TestProviders } from '../../../../common/mock'; -import { FETCH_NOTES_ERROR, NO_NOTES, NotesList } from './notes_list'; +import { DELETE_NOTE_ERROR, FETCH_NOTES_ERROR, NO_NOTES, NotesList } from './notes_list'; import { ReqStatus } from '../../../../notes/store/notes.slice'; const mockAddError = jest.fn(); @@ -19,6 +24,15 @@ jest.mock('../../../../common/hooks/use_app_toasts', () => ({ }), })); +const mockDispatch = jest.fn(); +jest.mock('react-redux', () => { + const original = jest.requireActual('react-redux'); + return { + ...original, + useDispatch: () => mockDispatch, + }; +}); + const renderNotesList = () => render( @@ -31,12 +45,20 @@ describe('NotesList', () => { const { getByTestId, getByText } = renderNotesList(); expect(getByTestId(`${NOTES_COMMENT_TEST_ID}-0`)).toBeInTheDocument(); expect(getByText('note-1')).toBeInTheDocument(); + expect(getByTestId(`${DELETE_NOTE_BUTTON_TEST_ID}-0`)).toBeInTheDocument(); }); it('should render loading spinner if notes are being fetched', () => { - const state = { ...mockGlobalState }; - state.notes.status.fetchNotesByDocumentId = ReqStatus.Loading; - const store = createMockStore(state); + const store = createMockStore({ + ...mockGlobalState, + notes: { + ...mockGlobalState.notes, + status: { + ...mockGlobalState.notes.status, + fetchNotesByDocumentId: ReqStatus.Loading, + }, + }, + }); const { getByTestId } = render( @@ -48,9 +70,16 @@ describe('NotesList', () => { }); it('should render no data message if no notes are present', () => { - const state = { ...mockGlobalState }; - state.notes.status.fetchNotesByDocumentId = ReqStatus.Succeeded; - const store = createMockStore(state); + const store = createMockStore({ + ...mockGlobalState, + notes: { + ...mockGlobalState.notes, + status: { + ...mockGlobalState.notes.status, + fetchNotesByDocumentId: ReqStatus.Succeeded, + }, + }, + }); const { getByText } = render( @@ -62,10 +91,20 @@ describe('NotesList', () => { }); it('should render error toast if fetching notes fails', () => { - const state = { ...mockGlobalState }; - state.notes.status.fetchNotesByDocumentId = ReqStatus.Failed; - state.notes.error.fetchNotesByDocumentId = { type: 'http', status: 500 }; - const store = createMockStore(state); + const store = createMockStore({ + ...mockGlobalState, + notes: { + ...mockGlobalState.notes, + status: { + ...mockGlobalState.notes.status, + fetchNotesByDocumentId: ReqStatus.Failed, + }, + error: { + ...mockGlobalState.notes.error, + fetchNotesByDocumentId: { type: 'http', status: 500 }, + }, + }, + }); render( @@ -78,10 +117,17 @@ describe('NotesList', () => { }); }); - it('should render create loading when user create a new note', () => { - const state = { ...mockGlobalState }; - state.notes.status.createNote = ReqStatus.Loading; - const store = createMockStore(state); + it('should render create loading when user creates a new note', () => { + const store = createMockStore({ + ...mockGlobalState, + notes: { + ...mockGlobalState.notes, + status: { + ...mockGlobalState.notes.status, + createNote: ReqStatus.Loading, + }, + }, + }); const { getByTestId } = render( @@ -91,4 +137,65 @@ describe('NotesList', () => { expect(getByTestId(ADD_NOTE_LOADING_TEST_ID)).toBeInTheDocument(); }); + + it('should dispatch delete action when user deletes a new note', () => { + const { getByTestId } = renderNotesList(); + + const deleteIcon = getByTestId(`${DELETE_NOTE_BUTTON_TEST_ID}-0`); + + expect(deleteIcon).toBeInTheDocument(); + expect(deleteIcon).not.toHaveAttribute('disabled'); + + deleteIcon.click(); + + expect(mockDispatch).toHaveBeenCalled(); + }); + + it('should have delete icons disabled and show spinner if a new note is being deleted', () => { + const store = createMockStore({ + ...mockGlobalState, + notes: { + ...mockGlobalState.notes, + status: { + ...mockGlobalState.notes.status, + deleteNote: ReqStatus.Loading, + }, + }, + }); + + const { getByTestId } = render( + + + + ); + + expect(getByTestId(`${DELETE_NOTE_BUTTON_TEST_ID}-0`)).toHaveAttribute('disabled'); + }); + + it('should render error toast if deleting a note fails', () => { + const store = createMockStore({ + ...mockGlobalState, + notes: { + ...mockGlobalState.notes, + status: { + ...mockGlobalState.notes.status, + deleteNote: ReqStatus.Failed, + }, + error: { + ...mockGlobalState.notes.error, + deleteNote: { type: 'http', status: 500 }, + }, + }, + }); + + render( + + + + ); + + expect(mockAddError).toHaveBeenCalledWith(null, { + title: DELETE_NOTE_ERROR, + }); + }); }); diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.tsx b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.tsx index a34afe6ad0e50..3ddff35c04bd3 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.tsx +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/notes_list.tsx @@ -5,17 +5,31 @@ * 2.0. */ -import React, { memo, useEffect } from 'react'; -import { EuiComment, EuiCommentList, EuiLoadingElastic, EuiMarkdownFormat } from '@elastic/eui'; -import { useSelector } from 'react-redux'; +import React, { memo, useCallback, useEffect, useState } from 'react'; +import { + EuiButtonIcon, + EuiComment, + EuiCommentList, + EuiLoadingElastic, + EuiMarkdownFormat, +} from '@elastic/eui'; +import { useDispatch, useSelector } from 'react-redux'; import { FormattedRelative } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; -import { ADD_NOTE_LOADING_TEST_ID, NOTES_COMMENT_TEST_ID, NOTES_LOADING_TEST_ID } from './test_ids'; +import { + ADD_NOTE_LOADING_TEST_ID, + DELETE_NOTE_BUTTON_TEST_ID, + NOTES_COMMENT_TEST_ID, + NOTES_LOADING_TEST_ID, +} from './test_ids'; import type { State } from '../../../../common/store'; import type { Note } from '../../../../../common/api/timeline'; import { + deleteNote, ReqStatus, selectCreateNoteStatus, + selectDeleteNoteError, + selectDeleteNoteStatus, selectFetchNotesByDocumentIdError, selectFetchNotesByDocumentIdStatus, selectNotesByDocumentId, @@ -34,6 +48,15 @@ export const FETCH_NOTES_ERROR = i18n.translate( export const NO_NOTES = i18n.translate('xpack.securitySolution.notes.noNotesLabel', { defaultMessage: 'No notes have been created for this document', }); +export const DELETE_NOTE = i18n.translate('xpack.securitySolution.notes.deleteNoteLabel', { + defaultMessage: 'Delete note', +}); +export const DELETE_NOTE_ERROR = i18n.translate( + 'xpack.securitySolution.notes.deleteNoteErrorLabel', + { + defaultMessage: 'Error deleting note', + } +); export interface NotesListProps { /** @@ -45,9 +68,11 @@ export interface NotesListProps { /** * Renders a list of notes for the document. * If a note belongs to a timeline, a timeline icon will be shown the top right corner. + * Also, a delete icon is shown in the top right corner to delete a note. * When a note is being created, the component renders a loading spinner when the new note is about to be added. */ export const NotesList = memo(({ eventId }: NotesListProps) => { + const dispatch = useDispatch(); const { addError: addErrorToast } = useAppToasts(); const fetchStatus = useSelector((state: State) => selectFetchNotesByDocumentIdStatus(state)); @@ -56,6 +81,18 @@ export const NotesList = memo(({ eventId }: NotesListProps) => { const createStatus = useSelector((state: State) => selectCreateNoteStatus(state)); + const deleteStatus = useSelector((state: State) => selectDeleteNoteStatus(state)); + const deleteError = useSelector((state: State) => selectDeleteNoteError(state)); + const [deletingNoteId, setDeletingNoteId] = useState(''); + + const deleteNoteFc = useCallback( + (noteId: string) => { + setDeletingNoteId(noteId); + dispatch(deleteNote({ id: noteId })); + }, + [dispatch] + ); + useEffect(() => { if (fetchStatus === ReqStatus.Failed && fetchError) { addErrorToast(null, { @@ -64,6 +101,14 @@ export const NotesList = memo(({ eventId }: NotesListProps) => { } }, [addErrorToast, fetchError, fetchStatus]); + useEffect(() => { + if (deleteStatus === ReqStatus.Failed && deleteError) { + addErrorToast(null, { + title: DELETE_NOTE_ERROR, + }); + } + }, [addErrorToast, deleteError, deleteStatus]); + if (fetchStatus === ReqStatus.Loading) { return ; } @@ -81,6 +126,18 @@ export const NotesList = memo(({ eventId }: NotesListProps) => { username={note.createdBy} timestamp={<>{note.created && }} event={ADDED_A_NOTE} + actions={ + deleteNoteFc(note.noteId)} + disabled={deletingNoteId !== note.noteId && deleteStatus === ReqStatus.Loading} + isLoading={deletingNoteId === note.noteId && deleteStatus === ReqStatus.Loading} + /> + } > {note.note || ''} diff --git a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts index cd49334abea7e..9b5c670f1ba26 100644 --- a/x-pack/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts +++ b/x-pack/plugins/security_solution/public/flyout/document_details/left/components/test_ids.ts @@ -97,3 +97,4 @@ export const NOTES_COMMENT_TEST_ID = `${PREFIX}NotesComment` as const; export const ADD_NOTE_LOADING_TEST_ID = `${PREFIX}AddNotesLoading` as const; export const ADD_NOTE_MARKDOWN_TEST_ID = `${PREFIX}AddNotesMarkdown` as const; export const ADD_NOTE_BUTTON_TEST_ID = `${PREFIX}AddNotesButton` as const; +export const DELETE_NOTE_BUTTON_TEST_ID = `${PREFIX}DeleteNotesButton` as const; diff --git a/x-pack/plugins/security_solution/public/notes/api/api.ts b/x-pack/plugins/security_solution/public/notes/api/api.ts index c1090de4fe631..302e70185cfba 100644 --- a/x-pack/plugins/security_solution/public/notes/api/api.ts +++ b/x-pack/plugins/security_solution/public/notes/api/api.ts @@ -54,3 +54,14 @@ export const generateNoteMock = (documentId: string) => ({ updated: new Date().getTime(), updatedBy: 'elastic', }); + +/** + * Deletes a note + */ +export const deleteNote = async (noteId: string) => { + const response = await KibanaServices.get().http.delete<{ data: unknown }>(NOTE_URL, { + body: JSON.stringify({ noteId }), + version: '2023-10-31', + }); + return response; +}; diff --git a/x-pack/plugins/security_solution/public/notes/store/notes.slice.test.ts b/x-pack/plugins/security_solution/public/notes/store/notes.slice.test.ts index 6fd6437f00c27..57347c1562837 100644 --- a/x-pack/plugins/security_solution/public/notes/store/notes.slice.test.ts +++ b/x-pack/plugins/security_solution/public/notes/store/notes.slice.test.ts @@ -7,6 +7,7 @@ import { createNote, + deleteNote, fetchNotesByDocumentId, initialNotesState, notesReducer, @@ -14,6 +15,8 @@ import { selectAllNotes, selectCreateNoteError, selectCreateNoteStatus, + selectDeleteNoteError, + selectDeleteNoteStatus, selectFetchNotesByDocumentIdError, selectFetchNotesByDocumentIdStatus, selectNoteById, @@ -31,8 +34,12 @@ const initialNonEmptyState = { [mockNote.noteId]: mockNote, }, ids: [mockNote.noteId], - status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Idle }, - error: { fetchNotesByDocumentId: null, createNote: null }, + status: { + fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Idle, + }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, }; describe('notesSlice', () => { @@ -41,13 +48,17 @@ describe('notesSlice', () => { expect(notesReducer(initalEmptyState, { type: 'unknown' })).toEqual({ entities: {}, ids: [], - status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Idle }, - error: { fetchNotesByDocumentId: null, createNote: null }, + status: { + fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Idle, + }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, }); }); describe('fetchNotesByDocumentId', () => { - it('should set correct state when fetching notes by document id', () => { + it('should set correct status state when fetching notes by document id', () => { const action = { type: fetchNotesByDocumentId.pending.type }; expect(notesReducer(initalEmptyState, action)).toEqual({ @@ -56,8 +67,9 @@ describe('notesSlice', () => { status: { fetchNotesByDocumentId: ReqStatus.Loading, createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Idle, }, - error: { fetchNotesByDocumentId: null, createNote: null }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, }); }); @@ -80,8 +92,9 @@ describe('notesSlice', () => { status: { fetchNotesByDocumentId: ReqStatus.Succeeded, createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Idle, }, - error: { fetchNotesByDocumentId: null, createNote: null }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, }); }); @@ -105,12 +118,13 @@ describe('notesSlice', () => { status: { fetchNotesByDocumentId: ReqStatus.Succeeded, createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Idle, }, - error: { fetchNotesByDocumentId: null, createNote: null }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, }); }); - it('should set correct state when error on fetch notes by document id', () => { + it('should set correct error state when failing to fetch notes by document id', () => { const action = { type: fetchNotesByDocumentId.rejected.type, error: 'error' }; expect(notesReducer(initalEmptyState, action)).toEqual({ @@ -119,14 +133,19 @@ describe('notesSlice', () => { status: { fetchNotesByDocumentId: ReqStatus.Failed, createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Idle, + }, + error: { + fetchNotesByDocumentId: 'error', + createNote: null, + deleteNote: null, }, - error: { fetchNotesByDocumentId: 'error', createNote: null }, }); }); }); describe('createNote', () => { - it('should set correct state when creating a note by document id', () => { + it('should set correct status state when creating a note by document id', () => { const action = { type: createNote.pending.type }; expect(notesReducer(initalEmptyState, action)).toEqual({ @@ -135,8 +154,9 @@ describe('notesSlice', () => { status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Loading, + deleteNote: ReqStatus.Idle, }, - error: { fetchNotesByDocumentId: null, createNote: null }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, }); }); @@ -159,12 +179,13 @@ describe('notesSlice', () => { status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Succeeded, + deleteNote: ReqStatus.Idle, }, - error: { fetchNotesByDocumentId: null, createNote: null }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, }); }); - it('should set correct state when error on create a note by document id', () => { + it('should set correct error state when failing to create a note by document id', () => { const action = { type: createNote.rejected.type, error: 'error' }; expect(notesReducer(initalEmptyState, action)).toEqual({ @@ -173,8 +194,67 @@ describe('notesSlice', () => { status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Failed, + deleteNote: ReqStatus.Idle, + }, + error: { + fetchNotesByDocumentId: null, + createNote: 'error', + deleteNote: null, + }, + }); + }); + }); + + describe('deleteNote', () => { + it('should set correct status state when deleting a note', () => { + const action = { type: deleteNote.pending.type }; + + expect(notesReducer(initalEmptyState, action)).toEqual({ + entities: {}, + ids: [], + status: { + fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Loading, + }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, + }); + }); + + it('should set correct state when success on deleting a note', () => { + const action = { + type: deleteNote.fulfilled.type, + payload: mockNote.noteId, + }; + + expect(notesReducer(initialNonEmptyState, action)).toEqual({ + entities: {}, + ids: [], + status: { + fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Succeeded, + }, + error: { fetchNotesByDocumentId: null, createNote: null, deleteNote: null }, + }); + }); + + it('should set correct state when failing to create a note by document id', () => { + const action = { type: deleteNote.rejected.type, error: 'error' }; + + expect(notesReducer(initalEmptyState, action)).toEqual({ + entities: {}, + ids: [], + status: { + fetchNotesByDocumentId: ReqStatus.Idle, + createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Failed, + }, + error: { + fetchNotesByDocumentId: null, + createNote: null, + deleteNote: 'error', }, - error: { fetchNotesByDocumentId: null, createNote: 'error' }, }); }); }); @@ -218,6 +298,14 @@ describe('notesSlice', () => { expect(selectCreateNoteError(mockGlobalState)).toEqual(null); }); + it('should return delete note status', () => { + expect(selectDeleteNoteStatus(mockGlobalState)).toEqual(ReqStatus.Idle); + }); + + it('should return delete note error', () => { + expect(selectDeleteNoteError(mockGlobalState)).toEqual(null); + }); + it('should return all notes for an existing document id', () => { expect(selectNotesByDocumentId(mockGlobalState, '1')).toEqual([mockNote]); }); diff --git a/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts b/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts index d644539844dd5..52a2805e765f6 100644 --- a/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts +++ b/x-pack/plugins/security_solution/public/notes/store/notes.slice.ts @@ -11,6 +11,7 @@ import { createSelector } from 'reselect'; import type { State } from '../../common/store'; import { createNote as createNoteApi, + deleteNote as deleteNoteApi, fetchNotesByDocumentId as fetchNotesByDocumentIdApi, } from '../api/api'; import type { NormalizedEntities, NormalizedEntity } from './normalize'; @@ -33,10 +34,12 @@ export interface NotesState extends EntityState { status: { fetchNotesByDocumentId: ReqStatus; createNote: ReqStatus; + deleteNote: ReqStatus; }; error: { fetchNotesByDocumentId: SerializedError | HttpError | null; createNote: SerializedError | HttpError | null; + deleteNote: SerializedError | HttpError | null; }; } @@ -48,10 +51,12 @@ export const initialNotesState: NotesState = notesAdapter.getInitialState({ status: { fetchNotesByDocumentId: ReqStatus.Idle, createNote: ReqStatus.Idle, + deleteNote: ReqStatus.Idle, }, error: { fetchNotesByDocumentId: null, createNote: null, + deleteNote: null, }, }); @@ -74,6 +79,15 @@ export const createNote = createAsyncThunk, { note: BareN } ); +export const deleteNote = createAsyncThunk( + 'notes/deleteNote', + async (args) => { + const { id } = args; + await deleteNoteApi(id); + return id; + } +); + const notesSlice = createSlice({ name: 'notes', initialState: initialNotesState, @@ -101,6 +115,17 @@ const notesSlice = createSlice({ .addCase(createNote.rejected, (state, action) => { state.status.createNote = ReqStatus.Failed; state.error.createNote = action.payload ?? action.error; + }) + .addCase(deleteNote.pending, (state) => { + state.status.deleteNote = ReqStatus.Loading; + }) + .addCase(deleteNote.fulfilled, (state, action) => { + notesAdapter.removeOne(state, action.payload); + state.status.deleteNote = ReqStatus.Succeeded; + }) + .addCase(deleteNote.rejected, (state, action) => { + state.status.deleteNote = ReqStatus.Failed; + state.error.deleteNote = action.payload ?? action.error; }); }, }); @@ -123,6 +148,10 @@ export const selectCreateNoteStatus = (state: State) => state.notes.status.creat export const selectCreateNoteError = (state: State) => state.notes.error.createNote; +export const selectDeleteNoteStatus = (state: State) => state.notes.status.deleteNote; + +export const selectDeleteNoteError = (state: State) => state.notes.error.deleteNote; + export const selectNotesByDocumentId = createSelector( [selectAllNotes, (state, documentId) => documentId], (notes, documentId) => notes.filter((note) => note.eventId === documentId) From e7c867f34a9d12b955f5c7df237b63bdfe2136e8 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Tue, 25 Jun 2024 12:28:32 -0700 Subject: [PATCH 12/22] [Maps] Use client-side authc.getCurrentUser from core.security (#186915) Part of https://github.com/elastic/kibana/issues/186574 Background: This PR serves as an example of a plugin migrating away from depending on the Security plugin, which is a high priority effort for the last release before 9.0. The Maps plugin uses the `authc.getCurrentUser` in the `es_search_source` utility. ### Checklist Delete any items that are not applicable to this PR. - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../sources/es_search_source/es_search_source.tsx | 9 ++------- x-pack/plugins/maps/public/kibana_services.ts | 1 - x-pack/plugins/maps/public/plugin.ts | 2 -- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx index 161acd3e5db73..76b2e17cb002e 100644 --- a/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx +++ b/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx @@ -19,12 +19,7 @@ import { Adapters } from '@kbn/inspector-plugin/common/adapters'; import { SortDirection, SortDirectionNumeric } from '@kbn/data-plugin/common'; import { getTileUrlParams } from '@kbn/maps-vector-tile-utils'; import { AbstractESSource } from '../es_source'; -import { - getHttp, - getSearchService, - getSecurityService, - getTimeFilter, -} from '../../../kibana_services'; +import { getCore, getHttp, getSearchService, getTimeFilter } from '../../../kibana_services'; import { addFieldToDSL, getField, @@ -532,7 +527,7 @@ export class ESSearchSource extends AbstractESSource implements IMvtVectorSource if (!(await this._isDrawingIndex())) { return {}; } - const user = await getSecurityService()?.authc.getCurrentUser(); + const user = await getCore().security.authc.getCurrentUser(); const timestamp = new Date().toISOString(); return { created: { diff --git a/x-pack/plugins/maps/public/kibana_services.ts b/x-pack/plugins/maps/public/kibana_services.ts index e7dfeb2e08957..9c11f56a7f5c7 100644 --- a/x-pack/plugins/maps/public/kibana_services.ts +++ b/x-pack/plugins/maps/public/kibana_services.ts @@ -90,7 +90,6 @@ export const getUrlForApp = () => coreStart.application.getUrlForApp; export const getNavigateToUrl = () => coreStart.application.navigateToUrl; export const getSavedObjectsTagging = () => pluginsStart.savedObjectsTagging; export const getPresentationUtilContext = () => pluginsStart.presentationUtil.ContextProvider; -export const getSecurityService = () => pluginsStart.security; export const getSpacesApi = () => pluginsStart.spaces; export const getTheme = () => coreStart.theme; export const getApplication = () => coreStart.application; diff --git a/x-pack/plugins/maps/public/plugin.ts b/x-pack/plugins/maps/public/plugin.ts index 42d40cc64e64a..169731af566fe 100644 --- a/x-pack/plugins/maps/public/plugin.ts +++ b/x-pack/plugins/maps/public/plugin.ts @@ -36,7 +36,6 @@ import type { FileUploadPluginStart } from '@kbn/file-upload-plugin/public'; import type { PresentationUtilPluginStart } from '@kbn/presentation-util-plugin/public'; import type { SavedObjectTaggingPluginStart } from '@kbn/saved-objects-tagging-plugin/public'; import type { ChartsPluginStart } from '@kbn/charts-plugin/public'; -import type { SecurityPluginStart } from '@kbn/security-plugin/public'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { CloudSetup } from '@kbn/cloud-plugin/public'; import type { LensPublicSetup } from '@kbn/lens-plugin/public'; @@ -123,7 +122,6 @@ export interface MapsPluginStartDependencies { visualizations: VisualizationsStart; savedObjectsTagging?: SavedObjectTaggingPluginStart; presentationUtil: PresentationUtilPluginStart; - security?: SecurityPluginStart; spaces?: SpacesPluginStart; mapsEms: MapsEmsPluginPublicStart; contentManagement: ContentManagementPublicStart; From 966b08247e209ac9b7fd6b0c386355322afb5a61 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Tue, 25 Jun 2024 12:29:23 -0700 Subject: [PATCH 13/22] [Data Visualizer] Use client-side authc.getCurrentUser from core.security (#186918) Part of https://github.com/elastic/kibana/issues/186574 Background: This PR serves as an example of a plugin migrating away from depending on the Security plugin, which is a high priority effort for the last release before 9.0. The Data Visualizer plugin uses the `authc.getCurrentUser` method as a means to use create FileBeat configuration example content. ### Checklist Delete any items that are not applicable to this PR. - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .../filebeat_config_flyout/filebeat_config_flyout.tsx | 8 +++----- .../application/common/types/data_visualizer_plugin.ts | 2 -- .../application/data_drift/data_drift_app_state.tsx | 2 -- .../file_data_visualizer/file_data_visualizer.tsx | 4 +--- .../grid_embeddable/field_stats_embeddable_wrapper.tsx | 2 -- .../index_data_visualizer/index_data_visualizer.tsx | 2 -- 6 files changed, 4 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx b/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx index a0053c6c64c1c..7682e771ac155 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx +++ b/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx @@ -50,11 +50,9 @@ export const FilebeatConfigFlyout: FC = ({ } = useDataVisualizerKibana(); useEffect(() => { - if (security !== undefined) { - security.authc.getCurrentUser().then((user) => { - setUsername(user.username === undefined ? null : user.username); - }); - } + security.authc.getCurrentUser().then((user) => { + setUsername(user.username === undefined ? null : user.username); + }); }, [security]); useEffect(() => { diff --git a/x-pack/plugins/data_visualizer/public/application/common/types/data_visualizer_plugin.ts b/x-pack/plugins/data_visualizer/public/application/common/types/data_visualizer_plugin.ts index cb2c3d680e5b4..cb2e90f7d4bae 100644 --- a/x-pack/plugins/data_visualizer/public/application/common/types/data_visualizer_plugin.ts +++ b/x-pack/plugins/data_visualizer/public/application/common/types/data_visualizer_plugin.ts @@ -16,7 +16,6 @@ import type { SavedSearchPublicPluginStart } from '@kbn/saved-search-plugin/publ import type { FileUploadPluginStart } from '@kbn/file-upload-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import type { MapsStartApi } from '@kbn/maps-plugin/public'; -import type { SecurityPluginSetup } from '@kbn/security-plugin/public'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; import type { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; @@ -35,7 +34,6 @@ export interface DataVisualizerStartDependencies { fileUpload: FileUploadPluginStart; maps: MapsStartApi; embeddable: EmbeddableStart; - security?: SecurityPluginSetup; share: SharePluginStart; lens?: LensPublicStart; charts: ChartsPluginStart; diff --git a/x-pack/plugins/data_visualizer/public/application/data_drift/data_drift_app_state.tsx b/x-pack/plugins/data_visualizer/public/application/data_drift/data_drift_app_state.tsx index a7d4af94a62c8..24c995ec0652d 100644 --- a/x-pack/plugins/data_visualizer/public/application/data_drift/data_drift_app_state.tsx +++ b/x-pack/plugins/data_visualizer/public/application/data_drift/data_drift_app_state.tsx @@ -68,7 +68,6 @@ export const DataDriftDetectionAppState: FC = ( maps, embeddable, share, - security, fileUpload, lens, dataViewFieldEditor, @@ -82,7 +81,6 @@ export const DataDriftDetectionAppState: FC = ( maps, embeddable, share, - security, fileUpload, lens, dataViewFieldEditor, diff --git a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx index 13b3511fc7fc1..01d9d2c37194f 100644 --- a/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx +++ b/x-pack/plugins/data_visualizer/public/application/file_data_visualizer/file_data_visualizer.tsx @@ -25,15 +25,13 @@ export type FileDataVisualizerSpec = typeof FileDataVisualizer; export const FileDataVisualizer: FC = ({ getAdditionalLinks, resultLinks }) => { const coreStart = getCoreStart(); - const { data, maps, embeddable, share, security, fileUpload, cloud, fieldFormats } = - getPluginsStart(); + const { data, maps, embeddable, share, fileUpload, cloud, fieldFormats } = getPluginsStart(); const services = { ...coreStart, data, maps, embeddable, share, - security, fileUpload, fieldFormats, }; diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/field_stats_embeddable_wrapper.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/field_stats_embeddable_wrapper.tsx index 4d547635eb504..a7e57e1e550b6 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/field_stats_embeddable_wrapper.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/embeddables/grid_embeddable/field_stats_embeddable_wrapper.tsx @@ -78,7 +78,6 @@ const FieldStatisticsWrapper = (props: FieldStatisticTableEmbeddableProps) => { maps, embeddable, share, - security, fileUpload, lens, dataViewFieldEditor, @@ -92,7 +91,6 @@ const FieldStatisticsWrapper = (props: FieldStatisticTableEmbeddableProps) => { maps, embeddable, share, - security, fileUpload, lens, dataViewFieldEditor, diff --git a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx index 2ad7500f7e693..9412f08172c48 100644 --- a/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx +++ b/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx @@ -311,7 +311,6 @@ export const IndexDataVisualizer: FC = ({ maps, embeddable, share, - security, fileUpload, lens, dataViewFieldEditor, @@ -325,7 +324,6 @@ export const IndexDataVisualizer: FC = ({ maps, embeddable, share, - security, fileUpload, lens, dataViewFieldEditor, From 53de504c6d54f5ceda2195a1a8b4e2c7ace92baf Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Tue, 25 Jun 2024 13:23:09 -0700 Subject: [PATCH 14/22] [Reporting] Unskip serverless functional test (#186676) ## Summary Partially address https://github.com/elastic/kibana/issues/186558 --- .../functional/test_suites/common/reporting/management.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts b/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts index bb875e7fac186..50b8f0919694a 100644 --- a/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts +++ b/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts @@ -70,8 +70,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await svlUserManager.invalidateApiKeyForRole(roleAuthc); }); - // Cant auth into the route as it's structured currently - xit(`user sees a job they've created`, async () => { + it(`user sees a job they've created`, async () => { const { job: { id: jobId }, } = await reportingAPI.createReportJobInternal( From 4ffd5307f7737b027c4b9831c621aa9aa1989fb8 Mon Sep 17 00:00:00 2001 From: Bharat Pasupula <123897612+bhapas@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:27:18 +0200 Subject: [PATCH 15/22] [Security GenAI] [ Integration Assistant ] Add unit tests for Integration Assistant plugin files (#186512) --- .../__jest__/fixtures/build_integration.ts | 47 +++++++++++ .../categorization_route.test.ts | 20 +++++ .../common/api/ecs/ecs_route.test.ts | 20 +++++ .../common/api/model/api_test.mock.ts | 82 +++++++++++++++++++ .../common/api/related/related_route.test.ts | 20 +++++ .../graphs/categorization/validate.test.ts | 55 +++++++++++++ 6 files changed, 244 insertions(+) create mode 100644 x-pack/plugins/integration_assistant/__jest__/fixtures/build_integration.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.test.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.test.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/model/api_test.mock.ts create mode 100644 x-pack/plugins/integration_assistant/common/api/related/related_route.test.ts create mode 100644 x-pack/plugins/integration_assistant/server/graphs/categorization/validate.test.ts diff --git a/x-pack/plugins/integration_assistant/__jest__/fixtures/build_integration.ts b/x-pack/plugins/integration_assistant/__jest__/fixtures/build_integration.ts new file mode 100644 index 0000000000000..78228d5a4cbca --- /dev/null +++ b/x-pack/plugins/integration_assistant/__jest__/fixtures/build_integration.ts @@ -0,0 +1,47 @@ +/* + * 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 { Integration } from '../../common/api/model/common_attributes'; + +export const testIntegration: Integration = { + name: 'integration', + title: 'Integration', + description: 'Integration description', + dataStreams: [ + { + name: 'datastream', + title: 'Datastream', + description: 'Datastream description', + inputTypes: ['filestream', 'tcp', 'udp'], + docs: [ + { + key: 'value', + anotherKey: 'anotherValue', + }, + ], + rawSamples: ['{"test1": "test1"}'], + pipeline: { + processors: [ + { + set: { + field: 'ecs.version', + value: '8.11.0', + }, + }, + { + rename: { + field: 'message', + target_field: 'event.original', + ignore_missing: true, + if: 'ctx.event?.original == null', + }, + }, + ], + }, + }, + ], +}; diff --git a/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.test.ts b/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.test.ts new file mode 100644 index 0000000000000..f7ef31f5fdb99 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/categorization/categorization_route.test.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. + */ + +import { expectParseSuccess } from '@kbn/zod-helpers'; +import { CategorizationRequestBody } from './categorization_route'; +import { getCategorizationRequestMock } from '../model/api_test.mock'; + +describe('Categorization request schema', () => { + test('full request validate', () => { + const payload: CategorizationRequestBody = getCategorizationRequestMock(); + + const result = CategorizationRequestBody.safeParse(payload); + expectParseSuccess(result); + expect(result.data).toEqual(payload); + }); +}); diff --git a/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.test.ts b/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.test.ts new file mode 100644 index 0000000000000..770c3ff96f675 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/ecs/ecs_route.test.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. + */ + +import { expectParseSuccess } from '@kbn/zod-helpers'; +import { EcsMappingRequestBody } from './ecs_route'; +import { getEcsMappingRequestMock } from '../model/api_test.mock'; + +describe('Ecs Mapping request schema', () => { + test('full request validate', () => { + const payload: EcsMappingRequestBody = getEcsMappingRequestMock(); + + const result = EcsMappingRequestBody.safeParse(payload); + expectParseSuccess(result); + expect(result.data).toEqual(payload); + }); +}); diff --git a/x-pack/plugins/integration_assistant/common/api/model/api_test.mock.ts b/x-pack/plugins/integration_assistant/common/api/model/api_test.mock.ts new file mode 100644 index 0000000000000..92208abd04832 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/model/api_test.mock.ts @@ -0,0 +1,82 @@ +/* + * 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 { BuildIntegrationRequestBody } from '../build_integration/build_integration'; +import type { CategorizationRequestBody } from '../categorization/categorization_route'; +import type { EcsMappingRequestBody } from '../ecs/ecs_route'; +import type { RelatedRequestBody } from '../related/related_route'; +import type { DataStream, Integration, Pipeline } from './common_attributes'; + +const rawSamples = ['{"test1": "test1"}']; + +export const getDataStreamMock = (): DataStream => ({ + description: 'Test description', + name: 'Test name', + inputTypes: ['filestream'], + title: 'Test title', + docs: [ + { + key: 'value', + anotherKey: 'anotherValue', + }, + ], + rawSamples, + pipeline: getPipelineMock(), +}); + +export const getIntegrationMock = (): Integration => ({ + description: 'Test description', + name: 'Test name', + title: 'Test title', + dataStreams: [getDataStreamMock()], +}); + +export const getPipelineMock = (): Pipeline => ({ + processors: [ + { + set: { + field: 'ecs.version', + value: '8.11.0', + }, + }, + { + rename: { + field: 'message', + target_field: 'event.original', + ignore_missing: true, + if: 'ctx.event?.original == null', + }, + }, + ], +}); + +export const getCategorizationRequestMock = (): CategorizationRequestBody => ({ + connectorId: 'test-connector-id', + currentPipeline: getPipelineMock(), + dataStreamName: 'test-data-stream-name', + packageName: 'test-package-name', + rawSamples, +}); + +export const getBuildIntegrationRequestMock = (): BuildIntegrationRequestBody => ({ + integration: getIntegrationMock(), +}); + +export const getEcsMappingRequestMock = (): EcsMappingRequestBody => ({ + rawSamples, + dataStreamName: 'test-data-stream-name', + packageName: 'test-package-name', + connectorId: 'test-connector-id', +}); + +export const getRelatedRequestMock = (): RelatedRequestBody => ({ + dataStreamName: 'test-data-stream-name', + packageName: 'test-package-name', + rawSamples, + connectorId: 'test-connector-id', + currentPipeline: getPipelineMock(), +}); diff --git a/x-pack/plugins/integration_assistant/common/api/related/related_route.test.ts b/x-pack/plugins/integration_assistant/common/api/related/related_route.test.ts new file mode 100644 index 0000000000000..8f69c13303056 --- /dev/null +++ b/x-pack/plugins/integration_assistant/common/api/related/related_route.test.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. + */ + +import { expectParseSuccess } from '@kbn/zod-helpers'; +import { RelatedRequestBody } from './related_route'; +import { getRelatedRequestMock } from '../model/api_test.mock'; + +describe('Related request schema', () => { + test('full request validate', () => { + const payload: RelatedRequestBody = getRelatedRequestMock(); + + const result = RelatedRequestBody.safeParse(payload); + expectParseSuccess(result); + expect(result.data).toEqual(payload); + }); +}); diff --git a/x-pack/plugins/integration_assistant/server/graphs/categorization/validate.test.ts b/x-pack/plugins/integration_assistant/server/graphs/categorization/validate.test.ts new file mode 100644 index 0000000000000..95c56c777a315 --- /dev/null +++ b/x-pack/plugins/integration_assistant/server/graphs/categorization/validate.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 { handleCategorizationValidation } from './validate'; +import type { CategorizationState } from '../../types'; +import { categorizationTestState } from '../../../__jest__/fixtures/categorization'; + +const testState: CategorizationState = categorizationTestState; + +describe('Testing categorization invalid category', () => { + it('handleCategorizationValidation()', async () => { + testState.pipelineResults = [{ test: 'testresult', event: { category: ['foo'] } }]; + const response = handleCategorizationValidation(testState); + expect(response.invalidCategorization).toEqual([ + { + error: + "field event.category's values (foo) is not one of the allowed values (api, authentication, configuration, database, driver, email, file, host, iam, intrusion_detection, library, malware, network, package, process, registry, session, threat, vulnerability, web)", + }, + ]); + expect(response.lastExecutedChain).toBe('handleCategorizationValidation'); + }); +}); + +describe('Testing categorization invalid type', () => { + it('handleCategorizationValidation()', async () => { + testState.pipelineResults = [{ test: 'testresult', event: { type: ['foo'] } }]; + const response = handleCategorizationValidation(testState); + expect(response.invalidCategorization).toEqual([ + { + error: + "field event.type's values (foo) is not one of the allowed values (access, admin, allowed, change, connection, creation, deletion, denied, end, error, group, indicator, info, installation, protocol, start, user)", + }, + ]); + expect(response.lastExecutedChain).toBe('handleCategorizationValidation'); + }); +}); + +describe('Testing categorization invalid compatibility', () => { + it('handleCategorizationValidation()', async () => { + testState.pipelineResults = [ + { test: 'testresult', event: { category: ['authentication'], type: ['access'] } }, + ]; + const response = handleCategorizationValidation(testState); + expect(response.invalidCategorization).toEqual([ + { + error: 'event.type (access) not compatible with any of the event.category (authentication)', + }, + ]); + expect(response.lastExecutedChain).toBe('handleCategorizationValidation'); + }); +}); From 0d802cb247ee77d0246824310a6a4e32df8a2454 Mon Sep 17 00:00:00 2001 From: Ryland Herrick Date: Tue, 25 Jun 2024 16:10:25 -0500 Subject: [PATCH 16/22] [Security Solution][Detection Engine] ML Cypress Improvements (#186831) ## Summary This PR contains a collection of fixes, mainly cherry-picked from #181926. Since some of these tests are failing sporadically on main, I'm opening this "test fix" PR for expedience while #181926 is still in review. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed * [Cypress * 100](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6385) * [Serverless Cypress * 100](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6386) --- .../rule_creation/machine_learning_rule.cy.ts | 27 +++++++++++------- .../cypress/objects/rule.ts | 4 +-- .../cypress/support/machine_learning.ts | 28 +++++++++++++++++++ .../cypress/tasks/alerts_detection_rules.ts | 2 +- .../cypress/tasks/create_new_rule.ts | 28 +++++++++++++------ 5 files changed, 67 insertions(+), 22 deletions(-) create mode 100644 x-pack/test/security_solution_cypress/cypress/support/machine_learning.ts diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/machine_learning_rule.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/machine_learning_rule.cy.ts index 9121e524ddbb4..0f90e406682f3 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/machine_learning_rule.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_creation/machine_learning_rule.cy.ts @@ -4,13 +4,11 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { isArray } from 'lodash'; import { formatMitreAttackDescription, getHumanizedDuration } from '../../../../helpers/rules'; import { getMachineLearningRule } from '../../../../objects/rule'; import { - CUSTOM_RULES_BTN, RISK_SCORE, RULES_MANAGEMENT_TABLE, RULE_NAME, @@ -53,13 +51,27 @@ import { login } from '../../../../tasks/login'; import { visit } from '../../../../tasks/navigation'; import { openRuleManagementPageViaBreadcrumbs } from '../../../../tasks/rules_management'; import { CREATE_RULE_URL } from '../../../../urls/navigation'; +import { forceStopAndCloseJob } from '../../../../support/machine_learning'; +import { deleteAlertsAndRules } from '../../../../tasks/api_calls/common'; describe('Machine Learning rules', { tags: ['@ess', '@serverless'] }, () => { const expectedUrls = (getMachineLearningRule().references ?? []).join(''); const expectedFalsePositives = (getMachineLearningRule().false_positives ?? []).join(''); const expectedTags = (getMachineLearningRule().tags ?? []).join(''); const expectedMitre = formatMitreAttackDescription(getMachineLearningRule().threat ?? []); - const expectedNumberOfRules = 1; + const expectedJobText = [ + 'Unusual Linux Network Activity', + 'Anomalous Process for a Linux Population', + ].join(''); + + before(() => { + const machineLearningJobIds = ([] as string[]).concat( + getMachineLearningRule().machine_learning_job_id + ); + // ensure no ML jobs are started before the suite + machineLearningJobIds.forEach((jobId) => forceStopAndCloseJob({ jobId })); + deleteAlertsAndRules(); + }); beforeEach(() => { login(); @@ -75,9 +87,7 @@ describe('Machine Learning rules', { tags: ['@ess', '@serverless'] }, () => { createAndEnableRule(); openRuleManagementPageViaBreadcrumbs(); - cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)'); - - expectNumberOfRules(RULES_MANAGEMENT_TABLE, expectedNumberOfRules); + expectNumberOfRules(RULES_MANAGEMENT_TABLE, 1); cy.get(RULE_NAME).should('have.text', mlRule.name); cy.get(RISK_SCORE).should('have.text', mlRule.risk_score); @@ -104,15 +114,12 @@ describe('Machine Learning rules', { tags: ['@ess', '@serverless'] }, () => { getDetails(ANOMALY_SCORE_DETAILS).should('have.text', mlRule.anomaly_threshold); getDetails(RULE_TYPE_DETAILS).should('have.text', 'Machine Learning'); getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); - const machineLearningJobsArray = isArray(mlRule.machine_learning_job_id) - ? mlRule.machine_learning_job_id - : [mlRule.machine_learning_job_id]; // With the #1912 ML rule improvement changes we enable jobs on rule creation. // Though, in cypress jobs enabling does not work reliably and job can be started or stopped. // Thus, we disable next check till we fix the issue with enabling jobs in cypress. // Relevant ticket: https://github.com/elastic/security-team/issues/5389 // cy.get(MACHINE_LEARNING_JOB_STATUS).should('have.text', 'StoppedStopped'); - cy.get(MACHINE_LEARNING_JOB_ID).should('have.text', machineLearningJobsArray.join('')); + cy.get(MACHINE_LEARNING_JOB_ID).should('have.text', expectedJobText); }); cy.get(SCHEDULE_DETAILS).within(() => { getDetails(RUNS_EVERY_DETAILS) diff --git a/x-pack/test/security_solution_cypress/cypress/objects/rule.ts b/x-pack/test/security_solution_cypress/cypress/objects/rule.ts index 04ba983664952..50e358515d922 100644 --- a/x-pack/test/security_solution_cypress/cypress/objects/rule.ts +++ b/x-pack/test/security_solution_cypress/cypress/objects/rule.ts @@ -361,8 +361,8 @@ export const getMachineLearningRule = ( ): MachineLearningRuleCreateProps => ({ type: 'machine_learning', machine_learning_job_id: [ - 'Unusual Linux Network Activity', - 'Anomalous Process for a Linux Population', + 'v3_linux_anomalous_network_activity', + 'v3_linux_anomalous_process_all_hosts', ], anomaly_threshold: 20, name: 'New ML Rule Test', diff --git a/x-pack/test/security_solution_cypress/cypress/support/machine_learning.ts b/x-pack/test/security_solution_cypress/cypress/support/machine_learning.ts new file mode 100644 index 0000000000000..e562a693865e3 --- /dev/null +++ b/x-pack/test/security_solution_cypress/cypress/support/machine_learning.ts @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { rootRequest } from '../tasks/api_calls/common'; + +/** + * Calls the internal ML Jobs API to force stop the datafeed of, and force close + * the job with the given ID. + * + * @param jobId the ID of the ML job to stop and close + * @returns the response from the force stop and close job request + */ +export const forceStopAndCloseJob = ({ jobId }: { jobId: string }) => + rootRequest({ + headers: { + 'elastic-api-version': 1, + }, + method: 'POST', + url: '/internal/ml/jobs/force_stop_and_close_job', + failOnStatusCode: false, + body: { + jobId, + }, + }); diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts b/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts index 97d6c34fdd040..7304a23f75e77 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/alerts_detection_rules.ts @@ -384,7 +384,7 @@ export const expectNumberOfRules = ( expectedNumber: number ) => { cy.log(`Expecting rules table to contain #${expectedNumber} rules`); - cy.get(tableSelector).find(RULES_ROW).should('have.length', expectedNumber); + cy.get(tableSelector).find(RULES_ROW).its('length').should('be.gte', expectedNumber); }; export const expectToContainRule = ( diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts b/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts index d9f0120ab0199..e8be51d0d3731 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/create_new_rule.ts @@ -802,21 +802,20 @@ export const continueFromDefineStep = () => { getDefineContinueButton().should('exist').click({ force: true }); }; -export const fillDefineMachineLearningRuleAndContinue = (rule: MachineLearningRuleCreateProps) => { +export const fillDefineMachineLearningRule = (rule: MachineLearningRuleCreateProps) => { const jobsAsArray = isArray(rule.machine_learning_job_id) ? rule.machine_learning_job_id : [rule.machine_learning_job_id]; - const text = jobsAsArray - .map((machineLearningJob) => `${machineLearningJob}{downArrow}{enter}`) - .join(''); cy.get(MACHINE_LEARNING_DROPDOWN_INPUT).click({ force: true }); - cy.get(MACHINE_LEARNING_DROPDOWN_INPUT).type(text); - - cy.get(MACHINE_LEARNING_DROPDOWN_INPUT).type('{esc}'); + cy.get(MACHINE_LEARNING_DROPDOWN_INPUT).type(optionsToComboboxText(jobsAsArray)); cy.get(ANOMALY_THRESHOLD_INPUT).type(`{selectall}${rule.anomaly_threshold}`, { force: true, }); +}; + +export const fillDefineMachineLearningRuleAndContinue = (rule: MachineLearningRuleCreateProps) => { + fillDefineMachineLearningRule(rule); getDefineContinueButton().should('exist').click({ force: true }); }; @@ -909,9 +908,20 @@ export const enablesAndPopulatesThresholdSuppression = ( cy.get(ALERT_SUPPRESSION_DURATION_PER_TIME_INTERVAL).should('be.enabled').should('be.checked'); }; +const optionsToComboboxText = (options: string[]) => { + return options.map((o) => `${o}{downArrow}{enter}{esc}`).join(''); +}; + export const fillAlertSuppressionFields = (fields: string[]) => { - fields.forEach((field) => { - cy.get(ALERT_SUPPRESSION_FIELDS_COMBO_BOX).type(`${field}{enter}`); + cy.get(ALERT_SUPPRESSION_FIELDS_COMBO_BOX).should('not.be.disabled'); + cy.get(ALERT_SUPPRESSION_FIELDS_COMBO_BOX).click(); + cy.get(ALERT_SUPPRESSION_FIELDS_COMBO_BOX).type(optionsToComboboxText(fields)); +}; + +export const clearAlertSuppressionFields = () => { + cy.get(ALERT_SUPPRESSION_FIELDS_COMBO_BOX).should('not.be.disabled'); + cy.get(ALERT_SUPPRESSION_FIELDS).within(() => { + cy.get(COMBO_BOX_CLEAR_BTN).click(); }); }; From ba1221904ce914aedcac8b1343ddc35523dce18c Mon Sep 17 00:00:00 2001 From: Khristinin Nikita Date: Wed, 26 Jun 2024 00:09:31 +0200 Subject: [PATCH 17/22] Manual rule run UX changes + copy (#186830) ## Manual rule run UX improvements - Change copy, mainly Backfill to Manual rule run - Move Manual run into separate sections - Not hide Manual run sections with empty state - Add tooltip for disabled manual rule run when open rule actions - Add limitations to modal window - Change auto-refresh to refresh button + add information about last update - Fix bug, when you run manual run and it's not showing in the manual rule run table - Change order for start finish date in execution log - Add technical preview to manual rule run section https://github.com/elastic/kibana/assets/7609147/d6616a87-7259-4ad8-b605-fb8ffb8c6e7e --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Nastasha Solomon <79124755+nastasha-solomon@users.noreply.github.com> --- .../execution_log_columns.tsx | 4 +- .../execution_log_table.tsx | 5 +- .../execution_log_table/translations.ts | 3 +- .../pages/rule_details/index.tsx | 19 ++- .../hooks/use_schedule_rule_run_mutation.ts | 8 ++ .../components/manual_rule_run/index.tsx | 14 ++ .../manual_rule_run/translations.ts | 15 ++ .../components/rule_backfills_info/index.tsx | 129 ++++++++++++------ .../rule_gaps/translations.ts | 93 +++++++++++-- .../rules_table/use_rules_table_actions.tsx | 3 +- .../rules/rule_actions_overflow/index.tsx | 5 + .../detection_engine/rules/translations.ts | 7 + .../rule_gaps/manual_rule_run.cy.ts | 4 +- .../rule_details/backfill_group.cy.ts | 6 +- 14 files changed, 245 insertions(+), 70 deletions(-) diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_columns.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_columns.tsx index 4428d6cca6de6..984f0f5dee926 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_columns.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_columns.tsx @@ -169,11 +169,11 @@ export const getSourceEventTimeRangeColumns = () => [ return backfill ? (
- +
{'-'}
- +
) : ( diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx index 1444dc8e0fd40..981f80f36f744 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/execution_log_table.tsx @@ -78,7 +78,7 @@ import { getSourceEventTimeRangeColumns, } from './execution_log_columns'; import { ExecutionLogSearchBar } from './execution_log_search_bar'; -import { RuleBackfillsInfo } from '../../../../rule_gaps/components/rule_backfills_info'; + import { useIsExperimentalFeatureEnabled } from '../../../../../common/hooks/use_experimental_features'; const EXECUTION_UUID_FIELD_NAME = 'kibana.alert.rule.execution.uuid'; @@ -594,9 +594,6 @@ const ExecutionLogTableComponent: React.FC = ({ itemIdToExpandedRowMap={rows.itemIdToExpandedRowMap} data-test-subj="executionsTable" /> - - - ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/translations.ts index f84e0b6b859c2..76b3f5483baad 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/execution_log_table/translations.ts @@ -93,7 +93,8 @@ export const COLUMN_SOURCE_EVENT_TIME_RANGE = i18n.translate( export const COLUMN_SOURCE_EVENT_TIME_RANGE_TOOLTIP = i18n.translate( 'xpack.securitySolution.detectionEngine.ruleDetails.ruleExecutionLog.sourceEventTimeRangeTooltip', { - defaultMessage: "Only for manual rule runs. Don't include additional lookback time.", + defaultMessage: + "Only applies to manual rule executions. If the rule has look-back time, it's included in the logged time range.", } ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx index 43491a1969fff..da80b8ff6d015 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_details_ui/pages/rule_details/index.tsx @@ -112,6 +112,7 @@ import { } from '../../../../detections/components/rules/rule_execution_status'; import { ExecutionEventsTable } from '../../../rule_monitoring'; import { ExecutionLogTable } from './execution_log_table/execution_log_table'; +import { RuleBackfillsInfo } from '../../../rule_gaps/components/rule_backfills_info'; import * as ruleI18n from '../../../../detections/pages/detection_engine/rules/translations'; @@ -785,13 +786,17 @@ const RuleDetailsPageComponent: React.FC = ({ /> - + <> + + + + diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/api/hooks/use_schedule_rule_run_mutation.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/api/hooks/use_schedule_rule_run_mutation.ts index 78e3c5cbe6ca5..98c8a436393ad 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/api/hooks/use_schedule_rule_run_mutation.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/api/hooks/use_schedule_rule_run_mutation.ts @@ -9,6 +9,7 @@ import type { UseMutationOptions } from '@tanstack/react-query'; import { useMutation } from '@tanstack/react-query'; import type { ScheduleBackfillProps } from '../../types'; import { scheduleRuleRun } from '../api'; +import { useInvalidateFindBackfillQuery } from './use_find_backfills_for_rules'; export const SCHEDULE_RULE_RUN_MUTATION_KEY = [ 'POST', @@ -18,8 +19,15 @@ export const SCHEDULE_RULE_RUN_MUTATION_KEY = [ export const useScheduleRuleRunMutation = ( options?: UseMutationOptions ) => { + const invalidateBackfillQuery = useInvalidateFindBackfillQuery(); return useMutation((scheduleOptions: ScheduleBackfillProps) => scheduleRuleRun(scheduleOptions), { ...options, + onSettled: (...args) => { + invalidateBackfillQuery(); + if (options?.onSettled) { + options.onSettled(...args); + } + }, mutationKey: SCHEDULE_RULE_RUN_MUTATION_KEY, }); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/index.tsx index 00a3e4b262aa7..37a4762254329 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/index.tsx @@ -14,6 +14,8 @@ import { EuiForm, EuiFormRow, useGeneratedHtmlId, + EuiCallOut, + EuiSpacer, } from '@elastic/eui'; import moment from 'moment'; import React, { useCallback, useMemo, useState } from 'react'; @@ -118,6 +120,18 @@ const ManualRuleRunModalComponent = ({ onCancel, onConfirm }: ManualRuleRunModal /> + + + + + + + + ); }; diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/translations.ts index 737a992b3a5a3..d9833232deb11 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/manual_rule_run/translations.ts @@ -68,3 +68,18 @@ export const MANUAL_RULE_RUN_START_DATE_OUT_OF_RANGE_ERROR = (maxDaysLookback: n defaultMessage: 'Manual rule run cannot be scheduled earlier than {maxDaysLookback, plural, =1 {# day} other {# days}} ago', }); + +export const MANUAL_RULE_RUN_ALERT_LIMITATIONS = i18n.translate( + 'xpack.securitySolution.manualRuleRun.alertLimitations', + { + defaultMessage: + 'To view alerts generated by this run, filter the Alerts page by the time range that was selected for this manual rule run.', + } +); + +export const MANUAL_RULE_RUN_NOTIFIACTIONS_LIMITATIONS = i18n.translate( + 'xpack.securitySolution.manualRuleRun.notificationsLimitations', + { + defaultMessage: 'Rule actions are not performed during manual rule runs.', + } +); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_backfills_info/index.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_backfills_info/index.tsx index 1c8a180207d2a..3a2a608d84431 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_backfills_info/index.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/components/rule_backfills_info/index.tsx @@ -6,12 +6,15 @@ */ import React, { useState } from 'react'; -import { EuiAutoRefresh, EuiBasicTable, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import type { - EuiBasicTableColumn, - CriteriaWithPagination, - OnRefreshChangeProps, +import { + EuiButton, + EuiBasicTable, + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiBetaBadge, } from '@elastic/eui'; +import type { EuiBasicTableColumn, CriteriaWithPagination } from '@elastic/eui'; import { useFindBackfillsForRules } from '../../api/hooks/use_find_backfills_for_rules'; import { StopBackfill } from './stop_backfill'; import { BackfillStatusInfo } from './backfill_status'; @@ -23,12 +26,15 @@ import { useUserData } from '../../../../detections/components/user_info'; import { getBackfillRowsFromResponse } from './utils'; import { HeaderSection } from '../../../../common/components/header_section'; import { useIsExperimentalFeatureEnabled } from '../../../../common/hooks/use_experimental_features'; +import { TableHeaderTooltipCell } from '../../../rule_management_ui/components/rules_table/table_header_tooltip_cell'; +import { TECHNICAL_PREVIEW, TECHNICAL_PREVIEW_TOOLTIP } from '../../../../common/translations'; +import { useKibana } from '../../../../common/lib/kibana'; -const AUTO_REFRESH_INTERVAL = 3000; const DEFAULT_PAGE_SIZE = 10; const getBackfillsTableColumns = (hasCRUDPermissions: boolean) => { const stopAction = { + name: i18n.BACKFILLS_TABLE_COLUMN_ACTION, render: (item: BackfillRow) => , width: '10%', }; @@ -36,18 +42,33 @@ const getBackfillsTableColumns = (hasCRUDPermissions: boolean) => { const columns: Array> = [ { field: 'status', - name: i18n.BACKFILLS_TABLE_COLUMN_STATUS, + name: ( + + ), render: (value: BackfillStatus) => , width: '10%', }, { field: 'created_at', - name: i18n.BACKFILLS_TABLE_COLUMN_CREATED_AT, + name: ( + + ), render: (value: 'string') => , width: '20%', }, { - name: i18n.BACKFILLS_TABLE_COLUMN_SOURCE_TIME_RANCE, + name: ( + + ), render: (value: BackfillRow) => ( <> @@ -60,31 +81,56 @@ const getBackfillsTableColumns = (hasCRUDPermissions: boolean) => { { field: 'error', align: 'right', - name: i18n.BACKFILLS_TABLE_COLUMN_ERROR, + name: ( + + ), 'data-test-subj': 'rule-backfills-column-error', }, { field: 'pending', align: 'right', - name: i18n.BACKFILLS_TABLE_COLUMN_PENDING, + name: ( + + ), 'data-test-subj': 'rule-backfills-column-pending', }, { field: 'running', align: 'right', - name: i18n.BACKFILLS_TABLE_COLUMN_RUNNING, + name: ( + + ), 'data-test-subj': 'rule-backfills-column-running', }, { field: 'complete', align: 'right', - name: i18n.BACKFILLS_TABLE_COLUMN_COMPLETED, + name: ( + + ), 'data-test-subj': 'rule-backfills-column-completed', }, { field: 'total', align: 'right', - name: i18n.BACKFILLS_TABLE_COLUMN_TOTAL, + name: ( + + ), 'data-test-subj': 'rule-backfills-column-total', }, ]; @@ -98,21 +144,18 @@ const getBackfillsTableColumns = (hasCRUDPermissions: boolean) => { export const RuleBackfillsInfo = React.memo<{ ruleId: string }>(({ ruleId }) => { const isManualRuleRunEnabled = useIsExperimentalFeatureEnabled('manualRuleRunEnabled'); - const [autoRefreshInterval, setAutoRefreshInterval] = useState(AUTO_REFRESH_INTERVAL); - const [isAutoRefresh, setIsAutoRefresh] = useState(false); const [pageIndex, setPageIndex] = useState(0); const [pageSize, setPageSize] = useState(DEFAULT_PAGE_SIZE); const [{ canUserCRUD }] = useUserData(); const hasCRUDPermissions = hasUserCRUDPermission(canUserCRUD); - - const { data, isLoading, isError } = useFindBackfillsForRules( + const { timelines } = useKibana().services; + const { data, isLoading, isError, refetch, dataUpdatedAt } = useFindBackfillsForRules( { ruleIds: [ruleId], page: pageIndex + 1, perPage: pageSize, }, { - refetchInterval: isAutoRefresh ? autoRefreshInterval : false, enabled: isManualRuleRunEnabled, } ); @@ -131,13 +174,6 @@ export const RuleBackfillsInfo = React.memo<{ ruleId: string }>(({ ruleId }) => totalItemCount: data?.total ?? 0, }; - if (data?.total === 0) return null; - - const handleRefreshChange = ({ isPaused, refreshInterval }: OnRefreshChangeProps) => { - setIsAutoRefresh(!isPaused); - setAutoRefreshInterval(refreshInterval); - }; - const handleTableChange: (params: CriteriaWithPagination) => void = ({ page, sort, @@ -148,23 +184,39 @@ export const RuleBackfillsInfo = React.memo<{ ruleId: string }>(({ ruleId }) => } }; + const handleRefresh = () => { + refetch(); + }; + return ( -
- + + - + + + + + + + + + {i18n.BACKFILL_TABLE_REFRESH} + + + + - + {timelines.getLastUpdated({ + showUpdating: isLoading, + updatedAt: dataUpdatedAt, + })} + (({ ruleId }) => error={isError ? 'error' : undefined} loading={isLoading} onChange={handleTableChange} - noItemsMessage={'not found'} /> -
+ ); }); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/translations.ts b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/translations.ts index cb77ec89524fc..c2297e237100b 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/translations.ts +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_gaps/translations.ts @@ -14,6 +14,13 @@ export const BACKFILLS_TABLE_COLUMN_STATUS = i18n.translate( } ); +export const BACKFILLS_TABLE_COLUMN_STATUS_TOOLTIP = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.statusTooltip', + { + defaultMessage: 'Overall status of execution', + } +); + export const BACKFILLS_TABLE_COLUMN_CREATED_AT = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.column.createdAt', { @@ -21,13 +28,27 @@ export const BACKFILLS_TABLE_COLUMN_CREATED_AT = i18n.translate( } ); -export const BACKFILLS_TABLE_COLUMN_SOURCE_TIME_RANCE = i18n.translate( +export const BACKFILLS_TABLE_COLUMN_CREATED_AT_TOOLTIP = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.createdAtTooltip', + { + defaultMessage: 'When the manual run started', + } +); + +export const BACKFILLS_TABLE_COLUMN_SOURCE_TIME_RANGE = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.column.sourceTimeRange', { defaultMessage: 'Source event time range', } ); +export const BACKFILLS_TABLE_COLUMN_SOURCE_TIME_RANGE_TOOLTIP = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.sourceTimeRangeTooltip', + { + defaultMessage: 'The date and time range selected for the manual run', + } +); + export const BACKFILLS_TABLE_COLUMN_ERROR = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.column.error', { @@ -35,6 +56,13 @@ export const BACKFILLS_TABLE_COLUMN_ERROR = i18n.translate( } ); +export const BACKFILLS_TABLE_COLUMN_ERROR_TOOLTIP = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.errorTooltip', + { + defaultMessage: 'The number of failed manual run rule executions', + } +); + export const BACKFILLS_TABLE_COLUMN_COMPLETED = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.column.completed', { @@ -42,6 +70,13 @@ export const BACKFILLS_TABLE_COLUMN_COMPLETED = i18n.translate( } ); +export const BACKFILLS_TABLE_COLUMN_COMPLETED_TOOLTIP = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.completedTooltip', + { + defaultMessage: 'The number of completed manual run rule executions', + } +); + export const BACKFILLS_TABLE_COLUMN_RUNNING = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.column.running', { @@ -49,6 +84,13 @@ export const BACKFILLS_TABLE_COLUMN_RUNNING = i18n.translate( } ); +export const BACKFILLS_TABLE_COLUMN_RUNNING_TOOLTIP = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.runningTooltip', + { + defaultMessage: 'The number of manual run rule executions that are in progress', + } +); + export const BACKFILLS_TABLE_COLUMN_PENDING = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.column.pending', { @@ -56,6 +98,13 @@ export const BACKFILLS_TABLE_COLUMN_PENDING = i18n.translate( } ); +export const BACKFILLS_TABLE_COLUMN_PENDING_TOOLTIP = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.pendingTooltip', + { + defaultMessage: 'The number of manual run rule executions that are waiting to execute', + } +); + export const BACKFILLS_TABLE_COLUMN_TOTAL = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.column.total', { @@ -63,17 +112,25 @@ export const BACKFILLS_TABLE_COLUMN_TOTAL = i18n.translate( } ); +export const BACKFILLS_TABLE_COLUMN_TOTAL_TOOLTIP = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.totalTooltip', + { + defaultMessage: + 'The total number of rule executions that will occur during the selected date and time range', + } +); + export const BACKFILLS_TABLE_STOP = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.stop', { - defaultMessage: 'Stop', + defaultMessage: 'Stop run', } ); export const BACKFILLS_TABLE_STOP_CONFIRMATION_TITLE = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.stop.confirmationTitle', { - defaultMessage: 'Are you sure you want to stop this run?', + defaultMessage: 'Stop this rule run', } ); @@ -87,42 +144,49 @@ export const BACKFILLS_TABLE_STOP_CONFIRMATION_CANCEL = i18n.translate( export const BACKFILLS_TABLE_STOP_CONFIRMATION_STOP_RUNS = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.stop.stopRuns', { - defaultMessage: 'Stop runs', + defaultMessage: 'Stop run', } ); export const BACKFILLS_TABLE_STOP_CONFIRMATION_BODY = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.stop.description', { - defaultMessage: 'All remaining rule runs will be stopped', + defaultMessage: 'All the pending rule executions for this manual rule run will be stopped', } ); export const BACKFILLS_TABLE_STOP_CONFIRMATION_SUCCESS = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.stop.confirmationSuccess', { - defaultMessage: 'Run stopped', + defaultMessage: 'Rule run stopped', } ); export const BACKFILLS_TABLE_STOP_CONFIRMATION_ERROR = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillsTable.stop.confirmationError', { - defaultMessage: 'Error stopping run', + defaultMessage: 'Error stopping rule run', } ); export const BACKFILL_TABLE_TITLE = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillTable.title', { - defaultMessage: 'Backfill runs', + defaultMessage: 'Manual runs', + } +); + +export const BACKFILL_TABLE_REFRESH = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillTable.refresh', + { + defaultMessage: 'Refresh', } ); export const BACKFILL_TABLE_SUBTITLE = i18n.translate( 'xpack.securitySolution.rule_gaps.backfillTable.subtitle', { - defaultMessage: 'View and manage backfill runs', + defaultMessage: 'View and manage active manual runs', } ); @@ -132,13 +196,20 @@ export const BACKFILL_SCHEDULE_SUCCESS = (numRules: number) => { values: { numRules }, defaultMessage: - 'Successfully scheduled backfill for {numRules, plural, =1 {# rule} other {# rules}}', + 'Successfully scheduled manual run for {numRules, plural, =1 {# rule} other {# rules}}', } ); export const BACKFILL_SCHEDULE_ERROR_TITLE = i18n.translate( 'xpack.securitySolution.containers.detectionEngine.backfillSchedule.scheduleRuleRunErrorTitle', { - defaultMessage: 'Error while scheduling backfill', + defaultMessage: 'Error while scheduling manual run', + } +); + +export const BACKFILLS_TABLE_COLUMN_ACTION = i18n.translate( + 'xpack.securitySolution.rule_gaps.backfillsTable.column.action', + { + defaultMessage: 'Action', } ); diff --git a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_rules_table_actions.tsx b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_rules_table_actions.tsx index dc4a0cb429b87..4af2fdd7ef356 100644 --- a/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_rules_table_actions.tsx +++ b/x-pack/plugins/security_solution/public/detection_engine/rule_management_ui/components/rules_table/use_rules_table_actions.tsx @@ -122,7 +122,8 @@ export const useRulesTableActions = ({ { type: 'icon', 'data-test-subj': 'manualRuleRunAction', - description: i18n.MANUAL_RULE_RUN, + description: (rule) => + !rule.enabled ? i18n.MANUAL_RULE_RUN_TOOLTIP : i18n.MANUAL_RULE_RUN, icon: 'play', name: i18n.MANUAL_RULE_RUN, onClick: async (rule: Rule) => { diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_actions_overflow/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_actions_overflow/index.tsx index 5be000d508195..6ed110483ecc4 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_actions_overflow/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_actions_overflow/index.tsx @@ -155,6 +155,11 @@ const RuleActionsOverflowComponent = ({ key={i18nActions.MANUAL_RULE_RUN} icon="play" disabled={!userHasPermissions || !rule.enabled} + toolTipContent={ + !userHasPermissions || !rule.enabled + ? i18nActions.MANUAL_RULE_RUN_TOOLTIP + : '' + } data-test-subj="rules-details-manual-rule-run" onClick={async () => { startTransaction({ name: SINGLE_RULE_ACTIONS.MANUAL_RULE_RUN }); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts index eb2d6b01b492f..b8e4063abb600 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/translations.ts @@ -584,6 +584,13 @@ export const MANUAL_RULE_RUN = i18n.translate( } ); +export const MANUAL_RULE_RUN_TOOLTIP = i18n.translate( + 'xpack.securitySolution.detectionEngine.rules.allRules.actions.manualRuleRunTooltip', + { + defaultMessage: 'Manual run available only for enabled rules', + } +); + export const COLUMN_RULE = i18n.translate( 'xpack.securitySolution.detectionEngine.rules.allRules.columns.ruleTitle', { diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_gaps/manual_rule_run.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_gaps/manual_rule_run.cy.ts index 28eaef22cc2e7..29e2379367c0b 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_gaps/manual_rule_run.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/detection_engine/rule_gaps/manual_rule_run.cy.ts @@ -32,7 +32,7 @@ describe('Manual rule run', { tags: ['@ess', '@serverless', '@skipInServerlessMK ); manualRuleRunFromDetailsPage(); - cy.get(TOASTER).should('have.text', 'Successfully scheduled backfill for 1 rule'); + cy.get(TOASTER).should('have.text', 'Successfully scheduled manual run for 1 rule'); }); it('schedule from rules management table', () => { @@ -42,7 +42,7 @@ describe('Manual rule run', { tags: ['@ess', '@serverless', '@skipInServerlessMK disableAutoRefresh(); manuallyRunFirstRule(); - cy.get(TOASTER).should('have.text', 'Successfully scheduled backfill for 1 rule'); + cy.get(TOASTER).should('have.text', 'Successfully scheduled manual run for 1 rule'); } ); }); diff --git a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts index 7413b8a8f02c7..2f97e2f3c0721 100644 --- a/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts +++ b/x-pack/test/security_solution_cypress/cypress/e2e/detection_response/rule_management/rule_details/backfill_group.cy.ts @@ -58,7 +58,7 @@ describe( interceptFindBackfills(); goToExecutionLogTab(); - cy.get(RULE_BACKFILLS_INFO_HEADEAR).contains('Backfill runs'); + cy.get(RULE_BACKFILLS_INFO_HEADEAR).contains('Manual runs'); getBackfillsTableRows().should('have.length', 2); getBackfillsTableRows().eq(0).contains('Pending'); getBackfillsTableRows().eq(0).find(RULE_BACKFILLS_COLUMN_ERROR).contains('1'); @@ -76,11 +76,11 @@ describe( getBackfillsTableRows().eq(0).find(RULE_BACKFILLS_DELETE_BUTTON).click(); - cy.get(RULE_BACKFILLS_DELETE_MODAL).contains('Are you sure you want to stop this run?'); + cy.get(RULE_BACKFILLS_DELETE_MODAL).contains('Stop this rule run'); interceptDeleteBackfill(FIRST_BACKFILL_ID, 'deleteBackfill'); cy.get(RULE_BACKFILL_DELETE_MODAL_CONFIRM_BUTTON).click(); cy.wait('@deleteBackfill'); - cy.get(TOASTER).contains('Run stopped'); + cy.get(TOASTER).contains('Rule run stopped'); }); } ); From f775a6a3f16758d22f8d94a006f0d155f66839ac Mon Sep 17 00:00:00 2001 From: Andrew Macri Date: Tue, 25 Jun 2024 19:42:13 -0400 Subject: [PATCH 18/22] [Security Solution] [Attack discovery] Improves Attack discovery code coverage (#186679) ## [Security Solution] [Attack discovery] Improves Attack discovery code coverage ### Summary This PR improves unit test coverage for the [Attack discovery](https://github.com/elastic/kibana/pull/181818) feature. ### Desk testing Run `node scripts/jest --watch x-pack/plugins/security_solution/public/attack_discovery --coverage` --- .../__mocks__/raw_attack_discoveries.ts | 24 + .../routes/attack_discovery/helpers.test.ts | 723 ++++++++++-------- .../attack_chain/axis_tick/index.test.tsx | 29 + .../attack/attack_chain/index.test.tsx | 30 + .../attack/attack_chain/tactic/index.test.tsx | 43 ++ .../attack/mini_attack_chain/index.test.tsx | 28 + .../helpers.test.ts | 30 + .../index.test.tsx | 102 +++ .../get_host_flyout_panel_props.test.ts | 44 ++ .../get_user_flyout_panel_props.test.ts | 26 + .../field_markdown_renderer/helpers.test.ts | 58 ++ .../field_markdown_renderer/index.test.tsx | 110 +++ .../index.test.tsx | 63 ++ .../actionable_summary/index.test.tsx | 109 +++ .../actions_placeholder/index.test.tsx | 23 + .../actions/alerts_badge/index.test.tsx | 21 + .../actions/index.test.tsx | 46 ++ .../actions/take_action/helpers.test.ts | 43 ++ .../actions/take_action/index.test.tsx | 47 ++ .../actions/use_add_to_case/index.test.tsx | 87 +++ .../use_add_to_existing_case/index.test.tsx | 142 ++++ .../attack_discovery_panel/index.test.tsx | 63 ++ .../tabs/alerts_tab/index.test.tsx | 27 + .../tabs/attack_discovery_tab/index.test.tsx | 139 ++++ .../tabs/attack_discovery_tab/index.tsx | 2 +- .../tabs/get_tabs.test.tsx | 63 ++ .../attack_discovery_panel/tabs/get_tabs.tsx | 2 +- .../tabs/index.test.tsx | 38 + .../title/index.test.tsx | 36 + .../view_in_ai_assistant/index.test.tsx | 66 ++ .../use_view_in_ai_assistant.test.ts | 86 +++ .../get_attack_discovery_markdown.test.tsx | 188 +++++ .../public/attack_discovery/helpers.test.tsx | 96 +++ .../public/attack_discovery/helpers.ts | 2 +- .../mock/mock_attack_discovery.ts | 37 + .../mock/mock_use_attack_discovery.ts | 84 ++ .../animated_counter/index.test.tsx | 25 + .../empty_prompt/animated_counter/index.tsx | 4 +- .../pages/empty_prompt/index.test.tsx | 150 ++++ .../pages/header/index.test.tsx | 183 +++++ .../loading_callout/countdown/index.test.tsx | 84 ++ .../generation_timing/index.test.tsx | 40 + .../last_times_popover/helpers.test.ts | 74 ++ .../last_times_popover/index.test.tsx | 59 ++ .../pages/loading_callout/index.test.tsx | 73 ++ .../info_popover_body/index.test.tsx | 55 ++ .../loading_messages/index.test.tsx | 43 ++ .../pages/page_title/index.test.tsx | 22 + .../pages/summary/index.test.tsx | 56 ++ .../pages/summary_count/index.test.tsx | 51 ++ .../pages/upgrade/index.test.tsx | 63 ++ .../use_attack_discovery/helpers.test.ts | 284 +++++++ .../get_anonymized_alerts.test.ts | 171 +++++ .../attack_discovery/get_anonymized_alerts.ts | 2 +- .../get_attack_discovery_prompt.test.ts | 30 + .../get_output_parser.test.ts | 31 + .../tools/attack_discovery/helpers.ts | 21 - 57 files changed, 3945 insertions(+), 333 deletions(-) create mode 100644 x-pack/plugins/elastic_assistant/server/__mocks__/raw_attack_discoveries.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/axis_tick/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/tactic/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack/mini_attack_chain/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/attack_discovery_markdown_parser/helpers.test.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/attack_discovery_markdown_parser/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/get_host_flyout_panel_props.test.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/get_user_flyout_panel_props.test.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/helpers.test.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actionable_summary/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/actions_placeholder/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/alerts_badge/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/helpers.test.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/use_add_to_case/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/use_add_to_existing_case/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/title/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.test.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/get_attack_discovery_markdown/get_attack_discovery_markdown.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/helpers.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/mock/mock_attack_discovery.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/animated_counter/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/header/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/generation_timing/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/helpers.test.ts create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/info_popover_body/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/loading_messages/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/page_title/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/summary/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/summary_count/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/pages/upgrade/index.test.tsx create mode 100644 x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/helpers.test.ts create mode 100644 x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_anonymized_alerts.test.ts create mode 100644 x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_attack_discovery_prompt.test.ts create mode 100644 x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_output_parser.test.ts delete mode 100644 x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/helpers.ts diff --git a/x-pack/plugins/elastic_assistant/server/__mocks__/raw_attack_discoveries.ts b/x-pack/plugins/elastic_assistant/server/__mocks__/raw_attack_discoveries.ts new file mode 100644 index 0000000000000..1c43f112da2bb --- /dev/null +++ b/x-pack/plugins/elastic_assistant/server/__mocks__/raw_attack_discoveries.ts @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * A mock response from invoking the `attack-discovery` tool. + * This is a JSON string that represents the response from the tool + */ +export const getRawAttackDiscoveriesMock = () => + '{\n "alertsContextCount": 20,\n "attackDiscoveries": [\n {\n "alertIds": [\n "9bb601522d0c0b83783488a27a3ede5bd6a788f4f1ceef07cc8f12ac55f27563",\n "b9d6df8ab34e36c6868c097ff28dd01075df85a5ac1f084ef569ee8c6a4cf660",\n "014b433c3436ef5325cadacc35b6cb2ba8932a9c2ea0ba26d899f95c6fb61395",\n "28017987e64abb6ac486f1410f977d97ebd3a7172189cfdf943a48a59b968066"\n ],\n "detailsMarkdown": "- {{ host.name cb186c4a-3d70-4878-8ffe-18d84b5df86f }} (macOS {{ host.os.version 13.4 }}) executed a suspicious process {{ process.name unix1 }} with command line {{ process.command_line /Users/james/unix1 /Users/james/library/Keychains/login.keychain-db TempTemp1234!! }}\\\\n- The process was spawned by another suspicious process {{ process.parent.name My Go Application.app }} with command line {{ process.parent.command_line /private/var/folders/_b/rmcpc65j6nv11ygrs50ctcjr0000gn/T/AppTranslocation/6D63F08A-011C-4511-8556-EAEF9AFD6340/d/Setup.app/Contents/MacOS/My Go Application.app }}\\\\n- The parent process was launched by the system process {{ process.parent.parent.name launchd }}\\\\n- Both the child and parent processes had untrusted code signatures\\\\n- The child process attempted to access the user\'s login keychain, potentially indicating credential theft",\n "entitySummaryMarkdown": "Suspicious activity on {{ host.name cb186c4a-3d70-4878-8ffe-18d84b5df86f }} by {{ user.name 3c8c81bd-0e52-4ce7-a836-48e718dfb6e4 }}",\n "mitreAttackTactics": [\n "Credential Access",\n "Defense Evasion",\n "Execution"\n ],\n "summaryMarkdown": "Suspicious activity detected on a macOS host involving a potentially malicious process attempting to access user credentials. The process was spawned by another untrusted process launched by the system, indicating a multi-stage attack potentially involving credential theft and defense evasion techniques.",\n "title": "Potential Credential Theft on macOS Host"\n },\n {\n "alertIds": [\n "64bcd8a322e6e6aebaee252982d0249cc96bdd75023ea05f58c228a7417c0dfc"\n ],\n "detailsMarkdown": "- {{ host.name cb186c4a-3d70-4878-8ffe-18d84b5df86f }} (macOS {{ host.os.version 13.4 }}) executed the system utility {{ process.name osascript }} with command line {{ process.command_line osascript -e display dialog \\"MacOS wants to access System Preferences\\\\n\\\\t\\\\t\\\\nPlease enter your password.\\" with title \\"System Preferences\\" with icon file \\"System:Library:CoreServices:CoreTypes.bundle:Contents:Resources:ToolbarAdvanced.icns\\" default answer \\"\\" giving up after 30 with hidden answer ¬ }}\\\\n- This appears to be an attempt to phish for user credentials by displaying a fake system dialog\\\\n- The osascript process was spawned by the suspicious process {{ process.parent.name My Go Application.app }} with untrusted code signature",\n "entitySummaryMarkdown": "Potential credential phishing attempt on {{ host.name cb186c4a-3d70-4878-8ffe-18d84b5df86f }} targeting {{ user.name 3c8c81bd-0e52-4ce7-a836-48e718dfb6e4 }}",\n "mitreAttackTactics": [\n "Credential Access",\n "Initial Access",\n "Execution"\n ],\n "summaryMarkdown": "A credential phishing attempt was detected on a macOS host, likely initiated by a malicious process. The attack used osascript to display a fake system dialog prompting the user to enter their password.",\n "title": "Credential Phishing Attempt on macOS"\n },\n {\n "alertIds": [\n "245b60b908ddd84cad06671e273aa7be50699abd27e59423be4415f38c4aeb99",\n "616ac711e967e07a9b725e66aa93321eabf29e4b51f9598a4a11f21ab7ed0f12",\n "035c0295b1c64fd2ebba1b751a3565fd6759942247e9df6e1496c5e332d51840"\n ],\n "detailsMarkdown": "- {{ host.name cb186c4a-3d70-4878-8ffe-18d84b5df86f }} (macOS {{ host.os.version 13.4 }}) executed a suspicious process {{ process.name My Go Application.app }} with command line {{ process.command_line xpcproxy application.Appify by Machine Box.My Go Application.20.23 }}\\\\n- This process had an untrusted code signature and was launched by the system process {{ process.parent.name launchd }}\\\\n- It appears to have spawned the process {{ process.name unix1 }} in an attempt to obfuscate its activities\\\\n- The unix1 process attempted to make itself executable by running {{ process.name chmod }} with arguments {{ process.command_line chmod 777 /Users/james/unix1 }}",\n "entitySummaryMarkdown": "Suspicious activity involving process obfuscation on {{ host.name cb186c4a-3d70-4878-8ffe-18d84b5df86f }} by {{ user.name fec12d87-2476-4b82-a50d-0829f3815a42 }}",\n "mitreAttackTactics": [\n "Defense Evasion",\n "Execution"\n ],\n "summaryMarkdown": "A suspicious process was detected on a macOS host that appeared to be attempting to obfuscate its activities by spawning other processes and making them executable. The initial process had an untrusted code signature, indicating potentially malicious intent.",\n "title": "Process Obfuscation on macOS Host"\n },\n {\n "alertIds": [\n "54901fb5b0ed88f0c8d737613868a3d62ebc541d31b757349bbe7999d868ce48"\n ],\n "detailsMarkdown": "- {{ host.name 23166d28-d6da-4801-b701-d21ce1a489e5 }} (Windows {{ host.os.version 21H2 (10.0.20348.1607) }}) created a suspicious script file {{ file.path C:\\\\ProgramData\\\\WindowsAppPool\\\\AppPool.vbs }}\\\\n- The file was created by a Microsoft Word process ({{ process.name WINWORD.EXE }}) with trusted code signature\\\\n- This may indicate an attempt to establish persistence or command-and-control through scripting",\n "entitySummaryMarkdown": "Suspicious script file created on {{ host.name 23166d28-d6da-4801-b701-d21ce1a489e5 }} by {{ user.name 45bec1b8-eb98-4ddc-aafb-e3f7e02236dc }}",\n "mitreAttackTactics": [\n "Command and Control",\n "Execution"\n ],\n "summaryMarkdown": "A suspicious VBScript file was created on a Windows host, potentially by an compromised Microsoft Word process. This may be an attempt to establish persistence or command-and-control capabilities through scripting.",\n "title": "Suspicious Script File Creation on Windows"\n },\n {\n "alertIds": [\n "7fe0025f2d2b0d32f04b0e533466666967a21a98adae7499cb05add3355b48fc",\n "3875cbad10604636b892d15f7ff753a02a37d3e4bbe91a39a0fcf72f89101e31",\n "bb2767ebef06a5dc2511e2b865f5ed012dfdf20081bc33cab5c9f20b99e01d8f",\n "76d99c72442819a019dfbf3936cda9a6c5713d84a9ae685b2c4e0bb55e5b9862",\n "0f985965cb3d3b14007873290b9fc8f26f1b6ca0945499dfb693787ea6569265"\n ],\n "detailsMarkdown": "- {{ host.name 9a0ea998-7ce5-4dbb-a690-9856eca617ac }} (Windows {{ host.os.version 21H2 (10.0.20348.1607) }}) executed a suspicious PowerShell script {{ process.command_line \\"C:\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe\\" -exec bypass -file C:\\\\ProgramData\\\\WindowsAppPool\\\\AppPool.ps1 }}\\\\n- The script was launched by the wscript process, which was spawned by a Microsoft Word process ({{ process.parent.name WINWORD.EXE }})\\\\n- The Word process also created a scheduled task to periodically execute the script\\\\n- The PowerShell script appears to be obfuscated, potentially to hide malicious activities\\\\n- This chain of events indicates a multi-stage attack potentially initiated by a malicious Office document",\n "entitySummaryMarkdown": "Suspicious PowerShell activity on {{ host.name 9a0ea998-7ce5-4dbb-a690-9856eca617ac }} by {{ user.name 45bec1b8-eb98-4ddc-aafb-e3f7e02236dc }}",\n "mitreAttackTactics": [\n "Initial Access",\n "Execution",\n "Defense Evasion"\n ],\n "summaryMarkdown": "A multi-stage attack was detected on a Windows host, potentially initiated by a malicious Microsoft Office document. The attack involved creating a scheduled task to execute an obfuscated PowerShell script, likely to hide malicious activities. This indicates techniques for initial access, execution, and defense evasion.",\n "title": "Multi-Stage Attack on Windows Host"\n },\n {\n "alertIds": [\n "a0c49fb228eca1685bd41df0ab66ca1977140de7916663e7a0918087220dd402",\n "a252ca3096831e3eeab07ab70e9269f98b5a66617b44d709425898813326ca63",\n "0ff7d411ca25a5b851e43562c9c660062624498f908ff4b63590d4b5304682af",\n "4d612c721e432598a5b7ea7bbeb2aaa2944c0a35e263d9984297b5416530c88f"\n ],\n "detailsMarkdown": "- {{ host.name 634eb7d8-0ce0-4591-b5f5-fb65803b89d8 }} (Windows {{ host.os.version 21H2 (10.0.20348.1607) }}) executed a suspicious PowerShell script {{ process.command_line \\"C:\\\\Windows\\\\System32\\\\WindowsPowerShell\\\\v1.0\\\\powershell.exe\\" -ep bypass -file \\"C:\\\\Users\\\\ADMINI~1\\\\AppData\\\\Local\\\\Temp\\\\2\\\\Package Installation Dir\\\\chch.ps1\\" }}\\\\n- The script was launched by the msiexec.exe process, which may indicate an attempt to use a trusted Windows utility for defense evasion\\\\n- Elastic Endpoint detected the Bb malware family in the PowerShell process memory\\\\n- The PowerShell process also made network connections, potentially for command-and-control or data exfiltration",\n "entitySummaryMarkdown": "Malware detected on {{ host.name 634eb7d8-0ce0-4591-b5f5-fb65803b89d8 }} targeting {{ user.name 45bec1b8-eb98-4ddc-aafb-e3f7e02236dc }}",\n "mitreAttackTactics": [\n "Defense Evasion",\n "Execution"\n ],\n "summaryMarkdown": "The B malware was detected on a Windows host, executed through a PowerShell script launched by the msiexec.exe process. This appears to be an attempt to use a trusted Windows utility for defense evasion. The malware process also made network connections, potentially for command-and-control or data exfiltration.",\n "title": "Bb Malware Execution on Windows"\n },\n {\n "alertIds": [\n "764c0944288db1704f7a0fff2db7fe19e8285fa4272dec828ae4186ba0dfd3b3",\n "85672064aeb762a1121139a6d98fd3c5f6be8f18b49e4504c3f5e5a36679afe7"\n ],\n "detailsMarkdown": "- {{ host.name d813c7ba-6141-4292-8f40-c800c27645a4 }} (Linux {{ host.os.version 22.04.1 }}) executed a suspicious process {{ process.command_line sh -c /bin/rm -f /dev/shm/kdmtmpflush;/bin/cp ./74ef6cc38f5a1a80148752b63c117e6846984debd2af806c65887195a8eccc56 /dev/shm/kdmtmpflush && /bin/chmod 755 /dev/shm/kdmtmpflush && /dev/shm/kdmtmpflush --init && /bin/rm -f /dev/shm/kdmtmpflush }}\\\\n- This copied a file with SHA256 hash {{ file.hash.sha256 74ef6cc38f5a1a80148752b63c117e6846984debd2af806c65887195a8eccc56 }} to /dev/shm/kdmtmpflush, made it executable, and executed it\\\\n- Elastic Endpoint detected the Door malware family associated with this file",\n "entitySummaryMarkdown": "Malware executed on {{ host.name d813c7ba-6141-4292-8f40-c800c27645a4 }} by {{ user.name fec12d87-2476-4b82-a50d-0829f3815a42 }}",\n "mitreAttackTactics": [\n "Execution"\n ],\n "summaryMarkdown": "The Door malware was executed on a Linux host by copying an untrusted file to a temporary path, making it executable, and running it. This indicates malicious code execution on the compromised system.",\n "title": "Door Malware Execution on Linux"\n }\n ]\n}'; + +export const getRawAttackDiscoveriesReplacementsMock = () => ({ + '3c8c81bd-0e52-4ce7-a836-48e718dfb6e4': 'james', + 'cb186c4a-3d70-4878-8ffe-18d84b5df86f': 'SRVMAC08', + 'fec12d87-2476-4b82-a50d-0829f3815a42': 'root', + '45bec1b8-eb98-4ddc-aafb-e3f7e02236dc': 'Administrator', + '23166d28-d6da-4801-b701-d21ce1a489e5': 'SRVWIN07-PRIV', + '9a0ea998-7ce5-4dbb-a690-9856eca617ac': 'SRVWIN07', + '634eb7d8-0ce0-4591-b5f5-fb65803b89d8': 'SRVWIN06', + 'd813c7ba-6141-4292-8f40-c800c27645a4': 'SRVNIX05', +}); diff --git a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts index 086af015d76e2..7f4baec88e60e 100644 --- a/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts +++ b/x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts @@ -4,6 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ + import { AuthenticatedUser } from '@kbn/core-security-common'; import moment from 'moment'; import { @@ -30,6 +31,12 @@ import { import { coreMock } from '@kbn/core/server/mocks'; import { transformESSearchToAttackDiscovery } from '../../ai_assistant_data_clients/attack_discovery/transforms'; import { getAttackDiscoverySearchEsMock } from '../../__mocks__/attack_discovery_schema.mock'; +import { elasticsearchClientMock } from '@kbn/core-elasticsearch-client-server-mocks'; + +import { + getAnonymizationFieldMock, + getUpdateAnonymizationFieldSchemaMock, +} from '../../__mocks__/anonymization_fields_schema.mock'; jest.mock('lodash/fp', () => ({ uniq: jest.fn((arr) => Array.from(new Set(arr))), @@ -61,6 +68,7 @@ const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); const mockLogger = loggerMock.create(); const mockTelemetry = coreMock.createSetup().analytics; const mockError = new Error('Test error'); + const mockAuthenticatedUser = { username: 'user', profile_uid: '1234', @@ -69,13 +77,25 @@ const mockAuthenticatedUser = { name: 'my_realm_name', }, } as AuthenticatedUser; + const mockApiConfig = { connectorId: 'connector-id', actionTypeId: '.bedrock', model: 'model', provider: OpenAiProviderType.OpenAi, }; + const mockCurrentAd = transformESSearchToAttackDiscovery(getAttackDiscoverySearchEsMock())[0]; + +const mockActions: ActionsPluginStart = {} as ActionsPluginStart; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const mockRequest: KibanaRequest = {} as unknown as KibanaRequest< + unknown, + unknown, + any, // eslint-disable-line @typescript-eslint/no-explicit-any + any // eslint-disable-line @typescript-eslint/no-explicit-any +>; + describe('helpers', () => { const date = '2024-03-28T22:27:28.000Z'; beforeAll(() => { @@ -92,6 +112,22 @@ describe('helpers', () => { updateAttackDiscovery.mockResolvedValue({}); }); describe('getAssistantToolParams', () => { + const alertsIndexPattern = '.alerts-security.alerts-default'; + const esClient = elasticsearchClientMock.createElasticsearchClient(); + const langChainTimeout = 1000; + const latestReplacements = {}; + const llm = new ActionsClientLlm({ + actions: mockActions, + connectorId: 'test-connecter-id', + llmType: 'bedrock', + logger: mockLogger, + request: mockRequest, + temperature: 0, + timeout: 580000, + }); + const onNewReplacements = jest.fn(); + const size = 20; + const mockParams = { actions: {} as unknown as ActionsPluginStart, alertsIndexPattern: 'alerts-*', @@ -127,364 +163,439 @@ describe('helpers', () => { ...REQUIRED_FOR_ATTACK_DISCOVERY, ]); }); - }); - - describe('addGenerationInterval', () => { - const generationInterval = { date: '2024-01-01T00:00:00Z', durationMs: 1000 }; - const existingIntervals = [ - { date: '2024-01-02T00:00:00Z', durationMs: 2000 }, - { date: '2024-01-03T00:00:00Z', durationMs: 3000 }, - ]; - - it('should add new interval and maintain length within MAX_GENERATION_INTERVALS', () => { - const result = addGenerationInterval(existingIntervals, generationInterval); - expect(result.length).toBeLessThanOrEqual(5); - expect(result).toContain(generationInterval); - }); - - it('should remove the oldest interval if exceeding MAX_GENERATION_INTERVALS', () => { - const longExistingIntervals = [...Array(5)].map((_, i) => ({ - date: `2024-01-0${i + 2}T00:00:00Z`, - durationMs: (i + 2) * 1000, - })); - const result = addGenerationInterval(longExistingIntervals, generationInterval); - expect(result.length).toBe(5); - expect(result).not.toContain(longExistingIntervals[4]); - }); - }); - - describe('updateAttackDiscoveryStatusToRunning', () => { - it('should update existing attack discovery to running', async () => { - const existingAd = { id: 'existing-id', backingIndex: 'index' }; - findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); - updateAttackDiscovery.mockResolvedValue(existingAd); - const result = await updateAttackDiscoveryStatusToRunning( - mockDataClient, - mockAuthenticatedUser, - mockApiConfig - ); - - expect(findAttackDiscoveryByConnectorId).toHaveBeenCalledWith({ - connectorId: mockApiConfig.connectorId, - authenticatedUser: mockAuthenticatedUser, + it('returns the expected AssistantToolParams when anonymizationFields are provided', () => { + const anonymizationFields = [ + getAnonymizationFieldMock(getUpdateAnonymizationFieldSchemaMock()), + ]; + + const result = getAssistantToolParams({ + actions: mockParams.actions, + alertsIndexPattern, + apiConfig: mockApiConfig, + anonymizationFields, + connectorTimeout: 1000, + latestReplacements, + esClient, + langChainTimeout, + logger: mockLogger, + onNewReplacements, + request: mockRequest, + size, }); - expect(updateAttackDiscovery).toHaveBeenCalledWith({ - attackDiscoveryUpdateProps: expect.objectContaining({ - status: attackDiscoveryStatus.running, - }), - authenticatedUser: mockAuthenticatedUser, - }); - expect(result).toEqual({ attackDiscoveryId: existingAd.id, currentAd: existingAd }); - }); - it('should create a new attack discovery if none exists', async () => { - const newAd = { id: 'new-id', backingIndex: 'index' }; - findAttackDiscoveryByConnectorId.mockResolvedValue(null); - createAttackDiscovery.mockResolvedValue(newAd); - - const result = await updateAttackDiscoveryStatusToRunning( - mockDataClient, - mockAuthenticatedUser, - mockApiConfig - ); - - expect(createAttackDiscovery).toHaveBeenCalledWith({ - attackDiscoveryCreate: expect.objectContaining({ - status: attackDiscoveryStatus.running, - }), - authenticatedUser: mockAuthenticatedUser, + expect(result).toEqual({ + alertsIndexPattern, + anonymizationFields: [...anonymizationFields, ...REQUIRED_FOR_ATTACK_DISCOVERY], + isEnabledKnowledgeBase: false, + chain: undefined, + esClient, + langChainTimeout, + llm, + logger: mockLogger, + modelExists: false, + onNewReplacements, + replacements: latestReplacements, + request: mockRequest, + size, }); - expect(result).toEqual({ attackDiscoveryId: newAd.id, currentAd: newAd }); }); - it('should throw an error if updating or creating attack discovery fails', async () => { - findAttackDiscoveryByConnectorId.mockResolvedValue(null); - createAttackDiscovery.mockResolvedValue(null); + it('returns the expected AssistantToolParams when anonymizationFields is undefined', () => { + const anonymizationFields = undefined; + + const result = getAssistantToolParams({ + actions: mockParams.actions, + alertsIndexPattern, + apiConfig: mockApiConfig, + anonymizationFields, + connectorTimeout: 1000, + latestReplacements, + esClient, + langChainTimeout, + logger: mockLogger, + onNewReplacements, + request: mockRequest, + size, + }); - await expect( - updateAttackDiscoveryStatusToRunning(mockDataClient, mockAuthenticatedUser, mockApiConfig) - ).rejects.toThrow('Could not create attack discovery for connectorId: connector-id'); + expect(result).toEqual({ + alertsIndexPattern, + anonymizationFields: [...REQUIRED_FOR_ATTACK_DISCOVERY], + isEnabledKnowledgeBase: false, + chain: undefined, + esClient, + langChainTimeout, + llm, + logger: mockLogger, + modelExists: false, + onNewReplacements, + replacements: latestReplacements, + request: mockRequest, + size, + }); }); - }); - - describe('updateAttackDiscoveryStatusToCanceled', () => { - const existingAd = { - id: 'existing-id', - backingIndex: 'index', - status: attackDiscoveryStatus.running, - }; - it('should update existing attack discovery to canceled', async () => { - findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); - updateAttackDiscovery.mockResolvedValue(existingAd); - - const result = await updateAttackDiscoveryStatusToCanceled( - mockDataClient, - mockAuthenticatedUser, - mockApiConfig.connectorId - ); - expect(findAttackDiscoveryByConnectorId).toHaveBeenCalledWith({ - connectorId: mockApiConfig.connectorId, - authenticatedUser: mockAuthenticatedUser, + describe('addGenerationInterval', () => { + const generationInterval = { date: '2024-01-01T00:00:00Z', durationMs: 1000 }; + const existingIntervals = [ + { date: '2024-01-02T00:00:00Z', durationMs: 2000 }, + { date: '2024-01-03T00:00:00Z', durationMs: 3000 }, + ]; + + it('should add new interval and maintain length within MAX_GENERATION_INTERVALS', () => { + const result = addGenerationInterval(existingIntervals, generationInterval); + expect(result.length).toBeLessThanOrEqual(5); + expect(result).toContain(generationInterval); }); - expect(updateAttackDiscovery).toHaveBeenCalledWith({ - attackDiscoveryUpdateProps: expect.objectContaining({ - status: attackDiscoveryStatus.canceled, - }), - authenticatedUser: mockAuthenticatedUser, + + it('should remove the oldest interval if exceeding MAX_GENERATION_INTERVALS', () => { + const longExistingIntervals = [...Array(5)].map((_, i) => ({ + date: `2024-01-0${i + 2}T00:00:00Z`, + durationMs: (i + 2) * 1000, + })); + const result = addGenerationInterval(longExistingIntervals, generationInterval); + expect(result.length).toBe(5); + expect(result).not.toContain(longExistingIntervals[4]); }); - expect(result).toEqual(existingAd); }); - it('should throw an error if attack discovery is not running', async () => { - findAttackDiscoveryByConnectorId.mockResolvedValue({ - ...existingAd, - status: attackDiscoveryStatus.succeeded, - }); - await expect( - updateAttackDiscoveryStatusToCanceled( + describe('updateAttackDiscoveryStatusToRunning', () => { + it('should update existing attack discovery to running', async () => { + const existingAd = { id: 'existing-id', backingIndex: 'index' }; + findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); + updateAttackDiscovery.mockResolvedValue(existingAd); + + const result = await updateAttackDiscoveryStatusToRunning( mockDataClient, mockAuthenticatedUser, - mockApiConfig.connectorId - ) - ).rejects.toThrow( - 'Connector id connector-id does not have a running attack discovery, and therefore cannot be canceled.' - ); - }); + mockApiConfig + ); + + expect(findAttackDiscoveryByConnectorId).toHaveBeenCalledWith({ + connectorId: mockApiConfig.connectorId, + authenticatedUser: mockAuthenticatedUser, + }); + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: expect.objectContaining({ + status: attackDiscoveryStatus.running, + }), + authenticatedUser: mockAuthenticatedUser, + }); + expect(result).toEqual({ attackDiscoveryId: existingAd.id, currentAd: existingAd }); + }); + + it('should create a new attack discovery if none exists', async () => { + const newAd = { id: 'new-id', backingIndex: 'index' }; + findAttackDiscoveryByConnectorId.mockResolvedValue(null); + createAttackDiscovery.mockResolvedValue(newAd); - it('should throw an error if attack discovery does not exist', async () => { - findAttackDiscoveryByConnectorId.mockResolvedValue(null); - await expect( - updateAttackDiscoveryStatusToCanceled( + const result = await updateAttackDiscoveryStatusToRunning( mockDataClient, mockAuthenticatedUser, - mockApiConfig.connectorId - ) - ).rejects.toThrow('Could not find attack discovery for connector id: connector-id'); + mockApiConfig + ); + + expect(createAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryCreate: expect.objectContaining({ + status: attackDiscoveryStatus.running, + }), + authenticatedUser: mockAuthenticatedUser, + }); + expect(result).toEqual({ attackDiscoveryId: newAd.id, currentAd: newAd }); + }); + + it('should throw an error if updating or creating attack discovery fails', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(null); + createAttackDiscovery.mockResolvedValue(null); + + await expect( + updateAttackDiscoveryStatusToRunning(mockDataClient, mockAuthenticatedUser, mockApiConfig) + ).rejects.toThrow('Could not create attack discovery for connectorId: connector-id'); + }); }); - it('should throw error if updateAttackDiscovery returns null', async () => { - findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); - updateAttackDiscovery.mockResolvedValue(null); - await expect( - updateAttackDiscoveryStatusToCanceled( + describe('updateAttackDiscoveryStatusToCanceled', () => { + const existingAd = { + id: 'existing-id', + backingIndex: 'index', + status: attackDiscoveryStatus.running, + }; + it('should update existing attack discovery to canceled', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); + updateAttackDiscovery.mockResolvedValue(existingAd); + + const result = await updateAttackDiscoveryStatusToCanceled( mockDataClient, mockAuthenticatedUser, mockApiConfig.connectorId - ) - ).rejects.toThrow('Could not update attack discovery for connector id: connector-id'); - }); - }); - - describe('updateAttackDiscoveries', () => { - const mockAttackDiscoveryId = 'attack-discovery-id'; - const mockLatestReplacements = {}; - const mockRawAttackDiscoveries = JSON.stringify({ - alertsContextCount: 5, - attackDiscoveries: [{ alertIds: ['alert-1', 'alert-2'] }, { alertIds: ['alert-3'] }], - }); - const mockSize = 10; - const mockStartTime = moment('2024-03-28T22:25:28.000Z'); - - const mockArgs = { - apiConfig: mockApiConfig, - attackDiscoveryId: mockAttackDiscoveryId, - authenticatedUser: mockAuthenticatedUser, - dataClient: mockDataClient, - latestReplacements: mockLatestReplacements, - logger: mockLogger, - rawAttackDiscoveries: mockRawAttackDiscoveries, - size: mockSize, - startTime: mockStartTime, - telemetry: mockTelemetry, - }; - - it('should update attack discoveries and report success telemetry', async () => { - await updateAttackDiscoveries(mockArgs); + ); + + expect(findAttackDiscoveryByConnectorId).toHaveBeenCalledWith({ + connectorId: mockApiConfig.connectorId, + authenticatedUser: mockAuthenticatedUser, + }); + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: expect.objectContaining({ + status: attackDiscoveryStatus.canceled, + }), + authenticatedUser: mockAuthenticatedUser, + }); + expect(result).toEqual(existingAd); + }); - expect(updateAttackDiscovery).toHaveBeenCalledWith({ - attackDiscoveryUpdateProps: { - alertsContextCount: 5, - attackDiscoveries: [{ alertIds: ['alert-1', 'alert-2'] }, { alertIds: ['alert-3'] }], + it('should throw an error if attack discovery is not running', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue({ + ...existingAd, status: attackDiscoveryStatus.succeeded, - id: mockAttackDiscoveryId, - replacements: mockLatestReplacements, - backingIndex: mockCurrentAd.backingIndex, - generationIntervals: [{ date, durationMs: 120000 }, ...mockCurrentAd.generationIntervals], - }, - authenticatedUser: mockAuthenticatedUser, + }); + await expect( + updateAttackDiscoveryStatusToCanceled( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig.connectorId + ) + ).rejects.toThrow( + 'Connector id connector-id does not have a running attack discovery, and therefore cannot be canceled.' + ); }); - expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_success', { - actionTypeId: mockApiConfig.actionTypeId, - alertsContextCount: 5, - alertsCount: 3, - configuredAlertsCount: mockSize, - discoveriesGenerated: 2, - durationMs: 120000, - model: mockApiConfig.model, - provider: mockApiConfig.provider, + it('should throw an error if attack discovery does not exist', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(null); + await expect( + updateAttackDiscoveryStatusToCanceled( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig.connectorId + ) + ).rejects.toThrow('Could not find attack discovery for connector id: connector-id'); + }); + it('should throw error if updateAttackDiscovery returns null', async () => { + findAttackDiscoveryByConnectorId.mockResolvedValue(existingAd); + updateAttackDiscovery.mockResolvedValue(null); + + await expect( + updateAttackDiscoveryStatusToCanceled( + mockDataClient, + mockAuthenticatedUser, + mockApiConfig.connectorId + ) + ).rejects.toThrow('Could not update attack discovery for connector id: connector-id'); }); }); - it('should update attack discoveries without generation interval if no discoveries are found', async () => { - const noDiscoveriesRaw = JSON.stringify({ - alertsContextCount: 0, - attackDiscoveries: [], + describe('updateAttackDiscoveries', () => { + const mockAttackDiscoveryId = 'attack-discovery-id'; + const mockLatestReplacements = {}; + const mockRawAttackDiscoveries = JSON.stringify({ + alertsContextCount: 5, + attackDiscoveries: [{ alertIds: ['alert-1', 'alert-2'] }, { alertIds: ['alert-3'] }], }); + const mockSize = 10; + const mockStartTime = moment('2024-03-28T22:25:28.000Z'); - await updateAttackDiscoveries({ - ...mockArgs, - rawAttackDiscoveries: noDiscoveriesRaw, + const mockArgs = { + apiConfig: mockApiConfig, + attackDiscoveryId: mockAttackDiscoveryId, + authenticatedUser: mockAuthenticatedUser, + dataClient: mockDataClient, + latestReplacements: mockLatestReplacements, + logger: mockLogger, + rawAttackDiscoveries: mockRawAttackDiscoveries, + size: mockSize, + startTime: mockStartTime, + telemetry: mockTelemetry, + }; + + it('should update attack discoveries and report success telemetry', async () => { + await updateAttackDiscoveries(mockArgs); + + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: { + alertsContextCount: 5, + attackDiscoveries: [{ alertIds: ['alert-1', 'alert-2'] }, { alertIds: ['alert-3'] }], + status: attackDiscoveryStatus.succeeded, + id: mockAttackDiscoveryId, + replacements: mockLatestReplacements, + backingIndex: mockCurrentAd.backingIndex, + generationIntervals: [ + { date, durationMs: 120000 }, + ...mockCurrentAd.generationIntervals, + ], + }, + authenticatedUser: mockAuthenticatedUser, + }); + + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_success', { + actionTypeId: mockApiConfig.actionTypeId, + alertsContextCount: 5, + alertsCount: 3, + configuredAlertsCount: mockSize, + discoveriesGenerated: 2, + durationMs: 120000, + model: mockApiConfig.model, + provider: mockApiConfig.provider, + }); }); - expect(updateAttackDiscovery).toHaveBeenCalledWith({ - attackDiscoveryUpdateProps: { + it('should update attack discoveries without generation interval if no discoveries are found', async () => { + const noDiscoveriesRaw = JSON.stringify({ alertsContextCount: 0, attackDiscoveries: [], - status: attackDiscoveryStatus.succeeded, - id: mockAttackDiscoveryId, - replacements: mockLatestReplacements, - backingIndex: mockCurrentAd.backingIndex, - }, - authenticatedUser: mockAuthenticatedUser, + }); + + await updateAttackDiscoveries({ + ...mockArgs, + rawAttackDiscoveries: noDiscoveriesRaw, + }); + + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: { + alertsContextCount: 0, + attackDiscoveries: [], + status: attackDiscoveryStatus.succeeded, + id: mockAttackDiscoveryId, + replacements: mockLatestReplacements, + backingIndex: mockCurrentAd.backingIndex, + }, + authenticatedUser: mockAuthenticatedUser, + }); + + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_success', { + actionTypeId: mockApiConfig.actionTypeId, + alertsContextCount: 0, + alertsCount: 0, + configuredAlertsCount: mockSize, + discoveriesGenerated: 0, + durationMs: 120000, + model: mockApiConfig.model, + provider: mockApiConfig.provider, + }); }); - expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_success', { - actionTypeId: mockApiConfig.actionTypeId, - alertsContextCount: 0, - alertsCount: 0, - configuredAlertsCount: mockSize, - discoveriesGenerated: 0, - durationMs: 120000, - model: mockApiConfig.model, - provider: mockApiConfig.provider, + it('should catch and log an error if raw attack discoveries is null', async () => { + await updateAttackDiscoveries({ + ...mockArgs, + rawAttackDiscoveries: null, + }); + expect(mockLogger.error).toHaveBeenCalledTimes(1); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: 'tool returned no attack discoveries', + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); }); - }); - it('should catch and log an error if raw attack discoveries is null', async () => { - await updateAttackDiscoveries({ - ...mockArgs, - rawAttackDiscoveries: null, - }); - expect(mockLogger.error).toHaveBeenCalledTimes(1); - expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { - actionTypeId: mockArgs.apiConfig.actionTypeId, - errorMessage: 'tool returned no attack discoveries', - model: mockArgs.apiConfig.model, - provider: mockArgs.apiConfig.provider, - }); - }); + it('should return and not call updateAttackDiscovery when getAttackDiscovery returns a canceled response', async () => { + getAttackDiscovery.mockResolvedValue({ + ...mockCurrentAd, + status: attackDiscoveryStatus.canceled, + }); + await updateAttackDiscoveries(mockArgs); - it('should return and not call updateAttackDiscovery when getAttackDiscovery returns a canceled response', async () => { - getAttackDiscovery.mockResolvedValue({ - ...mockCurrentAd, - status: attackDiscoveryStatus.canceled, + expect(mockLogger.error).not.toHaveBeenCalled(); + expect(updateAttackDiscovery).not.toHaveBeenCalled(); }); - await updateAttackDiscoveries(mockArgs); - expect(mockLogger.error).not.toHaveBeenCalled(); - expect(updateAttackDiscovery).not.toHaveBeenCalled(); - }); - - it('should log the error and report telemetry when getAttackDiscovery rejects', async () => { - getAttackDiscovery.mockRejectedValue(mockError); - await updateAttackDiscoveries(mockArgs); - - expect(mockLogger.error).toHaveBeenCalledWith(mockError); - expect(updateAttackDiscovery).not.toHaveBeenCalled(); - expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { - actionTypeId: mockArgs.apiConfig.actionTypeId, - errorMessage: mockError.message, - model: mockArgs.apiConfig.model, - provider: mockArgs.apiConfig.provider, + it('should log the error and report telemetry when getAttackDiscovery rejects', async () => { + getAttackDiscovery.mockRejectedValue(mockError); + await updateAttackDiscoveries(mockArgs); + + expect(mockLogger.error).toHaveBeenCalledWith(mockError); + expect(updateAttackDiscovery).not.toHaveBeenCalled(); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: mockError.message, + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); }); }); - }); - - describe('handleToolError', () => { - const mockArgs = { - apiConfig: mockApiConfig, - attackDiscoveryId: 'discovery-id', - authenticatedUser: mockAuthenticatedUser, - backingIndex: 'backing-index', - dataClient: mockDataClient, - err: mockError, - latestReplacements: {}, - logger: mockLogger, - telemetry: mockTelemetry, - }; - - it('should log the error and update attack discovery status to failed', async () => { - await handleToolError(mockArgs); - expect(mockLogger.error).toHaveBeenCalledWith(mockError); - expect(updateAttackDiscovery).toHaveBeenCalledWith({ - attackDiscoveryUpdateProps: { - status: attackDiscoveryStatus.failed, - attackDiscoveries: [], - backingIndex: 'foo', - failureReason: 'Test error', - id: 'discovery-id', - replacements: {}, - }, - authenticatedUser: mockArgs.authenticatedUser, - }); - expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { - actionTypeId: mockArgs.apiConfig.actionTypeId, - errorMessage: mockError.message, - model: mockArgs.apiConfig.model, - provider: mockArgs.apiConfig.provider, + describe('handleToolError', () => { + const mockArgs = { + apiConfig: mockApiConfig, + attackDiscoveryId: 'discovery-id', + authenticatedUser: mockAuthenticatedUser, + backingIndex: 'backing-index', + dataClient: mockDataClient, + err: mockError, + latestReplacements: {}, + logger: mockLogger, + telemetry: mockTelemetry, + }; + + it('should log the error and update attack discovery status to failed', async () => { + await handleToolError(mockArgs); + + expect(mockLogger.error).toHaveBeenCalledWith(mockError); + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: { + status: attackDiscoveryStatus.failed, + attackDiscoveries: [], + backingIndex: 'foo', + failureReason: 'Test error', + id: 'discovery-id', + replacements: {}, + }, + authenticatedUser: mockArgs.authenticatedUser, + }); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: mockError.message, + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); }); - }); - - it('should log the error and report telemetry when updateAttackDiscovery rejects', async () => { - updateAttackDiscovery.mockRejectedValue(mockError); - await handleToolError(mockArgs); - expect(mockLogger.error).toHaveBeenCalledWith(mockError); - expect(updateAttackDiscovery).toHaveBeenCalledWith({ - attackDiscoveryUpdateProps: { - status: attackDiscoveryStatus.failed, - attackDiscoveries: [], - backingIndex: 'foo', - failureReason: 'Test error', - id: 'discovery-id', - replacements: {}, - }, - authenticatedUser: mockArgs.authenticatedUser, + it('should log the error and report telemetry when updateAttackDiscovery rejects', async () => { + updateAttackDiscovery.mockRejectedValue(mockError); + await handleToolError(mockArgs); + + expect(mockLogger.error).toHaveBeenCalledWith(mockError); + expect(updateAttackDiscovery).toHaveBeenCalledWith({ + attackDiscoveryUpdateProps: { + status: attackDiscoveryStatus.failed, + attackDiscoveries: [], + backingIndex: 'foo', + failureReason: 'Test error', + id: 'discovery-id', + replacements: {}, + }, + authenticatedUser: mockArgs.authenticatedUser, + }); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: mockError.message, + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); }); - expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { - actionTypeId: mockArgs.apiConfig.actionTypeId, - errorMessage: mockError.message, - model: mockArgs.apiConfig.model, - provider: mockArgs.apiConfig.provider, - }); - }); - it('should return and not call updateAttackDiscovery when getAttackDiscovery returns a canceled response', async () => { - getAttackDiscovery.mockResolvedValue({ - ...mockCurrentAd, - status: attackDiscoveryStatus.canceled, - }); - await handleToolError(mockArgs); + it('should return and not call updateAttackDiscovery when getAttackDiscovery returns a canceled response', async () => { + getAttackDiscovery.mockResolvedValue({ + ...mockCurrentAd, + status: attackDiscoveryStatus.canceled, + }); + await handleToolError(mockArgs); - expect(mockTelemetry.reportEvent).not.toHaveBeenCalled(); - expect(updateAttackDiscovery).not.toHaveBeenCalled(); - }); + expect(mockTelemetry.reportEvent).not.toHaveBeenCalled(); + expect(updateAttackDiscovery).not.toHaveBeenCalled(); + }); - it('should log the error and report telemetry when getAttackDiscovery rejects', async () => { - getAttackDiscovery.mockRejectedValue(mockError); - await handleToolError(mockArgs); - - expect(mockLogger.error).toHaveBeenCalledWith(mockError); - expect(updateAttackDiscovery).not.toHaveBeenCalled(); - expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { - actionTypeId: mockArgs.apiConfig.actionTypeId, - errorMessage: mockError.message, - model: mockArgs.apiConfig.model, - provider: mockArgs.apiConfig.provider, + it('should log the error and report telemetry when getAttackDiscovery rejects', async () => { + getAttackDiscovery.mockRejectedValue(mockError); + await handleToolError(mockArgs); + + expect(mockLogger.error).toHaveBeenCalledWith(mockError); + expect(updateAttackDiscovery).not.toHaveBeenCalled(); + expect(mockTelemetry.reportEvent).toHaveBeenCalledWith('attack_discovery_error', { + actionTypeId: mockArgs.apiConfig.actionTypeId, + errorMessage: mockError.message, + model: mockArgs.apiConfig.model, + provider: mockArgs.apiConfig.provider, + }); }); }); }); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/axis_tick/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/axis_tick/index.test.tsx new file mode 100644 index 0000000000000..4dcd772d783bd --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/axis_tick/index.test.tsx @@ -0,0 +1,29 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; + +import { AxisTick } from '.'; + +describe('AxisTick', () => { + it('renders the top cell', async () => { + const { getByTestId } = render(); + + const topCell = getByTestId('topCell'); + + expect(topCell).toBeInTheDocument(); + }); + + it('renders the bottom cell', async () => { + const { getByTestId } = render(); + + const bottomCell = getByTestId('bottomCell'); + + expect(bottomCell).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/index.test.tsx new file mode 100644 index 0000000000000..195a5fe49dd19 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/index.test.tsx @@ -0,0 +1,30 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { getTacticMetadata } from '../../helpers'; +import { AttackChain } from '.'; + +import { mockAttackDiscovery } from '../../mock/mock_attack_discovery'; + +describe('AttackChain', () => { + it('renders the expected tactics', () => { + // get detected tactics from the attack discovery: + const tacticMetadata = getTacticMetadata(mockAttackDiscovery).filter( + (tactic) => tactic.detected + ); + expect(tacticMetadata.length).toBeGreaterThan(0); // test pre-condition + + render(); + + tacticMetadata?.forEach((tactic) => { + expect(screen.getByText(tactic.name)).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/tactic/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/tactic/index.test.tsx new file mode 100644 index 0000000000000..9c4166a43d620 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack/attack_chain/tactic/index.test.tsx @@ -0,0 +1,43 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Tactic } from '.'; + +describe('Tactic', () => { + const tactic = 'Privilege Escalation'; + + it('renders the tactic name', () => { + render(); + + const tacticText = screen.getByTestId('tacticText'); + + expect(tacticText).toHaveTextContent(tactic); + }); + + const detectedTestCases: boolean[] = [true, false]; + + detectedTestCases.forEach((detected) => { + it(`renders the inner circle when detected is ${detected}`, () => { + render(); + + const innerCircle = screen.getByTestId('innerCircle'); + + expect(innerCircle).toBeInTheDocument(); + }); + + it(`renders the outerCircle circle when detected is ${detected}`, () => { + render(); + + const outerCircle = screen.getByTestId('outerCircle'); + + expect(outerCircle).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack/mini_attack_chain/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack/mini_attack_chain/index.test.tsx new file mode 100644 index 0000000000000..c9923754d25da --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack/mini_attack_chain/index.test.tsx @@ -0,0 +1,28 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import type { TacticMetadata } from '../../helpers'; +import { getTacticMetadata } from '../../helpers'; +import { mockAttackDiscovery } from '../../mock/mock_attack_discovery'; +import { MiniAttackChain } from '.'; + +describe('MiniAttackChain', () => { + it('displays the expected number of circles', () => { + // get detected tactics from the attack discovery: + const tacticMetadata: TacticMetadata[] = getTacticMetadata(mockAttackDiscovery); + expect(tacticMetadata.length).toBeGreaterThan(0); // test pre-condition + + render(); + + const circles = screen.getAllByTestId('circle'); + + expect(circles.length).toEqual(tacticMetadata.length); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/attack_discovery_markdown_parser/helpers.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/attack_discovery_markdown_parser/helpers.test.ts new file mode 100644 index 0000000000000..fd3ada8f6bdd9 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/attack_discovery_markdown_parser/helpers.test.ts @@ -0,0 +1,30 @@ +/* + * 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 { getIconFromFieldName } from './helpers'; + +describe('helpers', () => { + describe('getIconFromFieldName', () => { + it('returns the expected icon for a known field name', () => { + const fieldName = 'host.name'; + const expectedIcon = 'desktop'; + + const icon = getIconFromFieldName(fieldName); + + expect(icon).toEqual(expectedIcon); + }); + + it('returns an empty string for an unknown field name', () => { + const fieldName = 'unknown.field'; + const emptyIcon = ''; + + const icon = getIconFromFieldName(fieldName); + + expect(icon).toEqual(emptyIcon); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/attack_discovery_markdown_parser/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/attack_discovery_markdown_parser/index.test.tsx new file mode 100644 index 0000000000000..5772272673b67 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/attack_discovery_markdown_parser/index.test.tsx @@ -0,0 +1,102 @@ +/* + * 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 { + EuiMarkdownFormat, + getDefaultEuiMarkdownParsingPlugins, + getDefaultEuiMarkdownProcessingPlugins, +} from '@elastic/eui'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TestProviders } from '../../../common/mock'; +import { getFieldMarkdownRenderer } from '../field_markdown_renderer'; +import { AttackDiscoveryMarkdownParser } from '.'; + +describe('AttackDiscoveryMarkdownParser', () => { + it('parsees markdown with valid fields', () => { + const attackDiscoveryParsingPluginList = [ + ...getDefaultEuiMarkdownParsingPlugins(), + AttackDiscoveryMarkdownParser, + ]; + + const markdownWithValidFields = ` + The following attack chain was detected involving Microsoft Office documents on multiple hosts: + +- On {{ host.name 39054a91-67f9-46fa-b9d1-85f928d4cd1b }}, a malicious Microsoft Office document was opened by {{ user.name 2c13d131-8fab-41b9-841e-669c66315a23 }}. +- This document launched a child process to write and execute a malicious script file named "AppPool.vbs". +- The "AppPool.vbs" script then spawned PowerShell to execute an obfuscated script payload from "AppPool.ps1". +- On {{ host.name 5149b291-72d0-4373-93ec-c117477932fe }}, a similar attack involving a malicious Office document and the creation of "AppPool.vbs" was detected and prevented. + +This appears to be a malware attack delivered via spearphishing, likely exploiting a vulnerability in Microsoft Office to gain initial access and then using PowerShell for execution and obfuscation. The attacker employed defense evasion techniques like script obfuscation and system binary proxies like "wscript.exe" and "mshta.exe". Mitigations should focus on patching Office vulnerabilities, restricting script execution, and enhancing email security controls. + `; + + const processingPluginList = getDefaultEuiMarkdownProcessingPlugins(); + processingPluginList[1][1].components.fieldPlugin = getFieldMarkdownRenderer(false); + + render( + + + {markdownWithValidFields} + + + ); + + const result = screen.getByTestId('attackDiscoveryMarkdownFormatter'); + + expect(result).toHaveTextContent( + 'The following attack chain was detected involving Microsoft Office documents on multiple hosts: On 39054a91-67f9-46fa-b9d1-85f928d4cd1b, a malicious Microsoft Office document was opened by 2c13d131-8fab-41b9-841e-669c66315a23. This document launched a child process to write and execute a malicious script file named "AppPool.vbs". The "AppPool.vbs" script then spawned PowerShell to execute an obfuscated script payload from "AppPool.ps1". On 5149b291-72d0-4373-93ec-c117477932fe, a similar attack involving a malicious Office document and the creation of "AppPool.vbs" was detected and prevented. This appears to be a malware attack delivered via spearphishing, likely exploiting a vulnerability in Microsoft Office to gain initial access and then using PowerShell for execution and obfuscation. The attacker employed defense evasion techniques like script obfuscation and system binary proxies like "wscript.exe" and "mshta.exe". Mitigations should focus on patching Office vulnerabilities, restricting script execution, and enhancing email security controls.' + ); + }); + + it('parsees markdown with invalid fields', () => { + const attackDiscoveryParsingPluginList = [ + ...getDefaultEuiMarkdownParsingPlugins(), + AttackDiscoveryMarkdownParser, + ]; + + const markdownWithInvalidFields = ` + The following attack chain was detected involving Microsoft Office documents on multiple hosts: + +- On {{ host.name 39054a91-67f9-46fa-b9d1-85f928d4cd1b }}, a malicious Microsoft Office document was opened by {{ user.name }}. +- This document launched a child process to write and execute a malicious script file named "AppPool.vbs". +- The "AppPool.vbs" script then spawned PowerShell to execute an obfuscated script payload from "AppPool.ps1". +- On {{ 5149b291-72d0-4373-93ec-c117477932fe }}, a similar attack involving a malicious Office document and the creation of "AppPool.vbs" was detected and prevented. + +This appears to be a malware attack delivered via spearphishing, likely exploiting a vulnerability in Microsoft Office to gain initial access and then using PowerShell for execution and obfuscation. The attacker employed defense evasion techniques like script obfuscation and system binary proxies like "wscript.exe" and "mshta.exe". Mitigations should focus on patching Office vulnerabilities, restricting script execution, and enhancing email security controls. {{ foo.bar baz }} + `; + + const processingPluginList = getDefaultEuiMarkdownProcessingPlugins(); + processingPluginList[1][1].components.fieldPlugin = getFieldMarkdownRenderer(false); + + render( + + + {markdownWithInvalidFields} + + + ); + + const result = screen.getByTestId('attackDiscoveryMarkdownFormatter'); + + expect(result).toHaveTextContent( + 'The following attack chain was detected involving Microsoft Office documents on multiple hosts: On 39054a91-67f9-46fa-b9d1-85f928d4cd1b, a malicious Microsoft Office document was opened by . This document launched a child process to write and execute a malicious script file named "AppPool.vbs". The "AppPool.vbs" script then spawned PowerShell to execute an obfuscated script payload from "AppPool.ps1". On (Empty string), a similar attack involving a malicious Office document and the creation of "AppPool.vbs" was detected and prevented. This appears to be a malware attack delivered via spearphishing, likely exploiting a vulnerability in Microsoft Office to gain initial access and then using PowerShell for execution and obfuscation. The attacker employed defense evasion techniques like script obfuscation and system binary proxies like "wscript.exe" and "mshta.exe". Mitigations should focus on patching Office vulnerabilities, restricting script execution, and enhancing email security controls. baz' + ); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/get_host_flyout_panel_props.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/get_host_flyout_panel_props.test.ts new file mode 100644 index 0000000000000..ea42a7ec1b045 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/get_host_flyout_panel_props.test.ts @@ -0,0 +1,44 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getHostFlyoutPanelProps, isHostName } from './get_host_flyout_panel_props'; + +describe('getHostFlyoutPanelProps', () => { + describe('isHostName', () => { + it('returns true for "host.name"', () => { + const result = isHostName('host.name'); + + expect(result).toBe(true); + }); + + it('returns true for "host.hostname"', () => { + const result = isHostName('host.hostname'); + + expect(result).toBe(true); + }); + + it('returns false for other field names', () => { + const result = isHostName('some.other.field'); + + expect(result).toBe(false); + }); + }); + + describe('getHostFlyoutPanelProps', () => { + it('returns the correct FlyoutPanelProps', () => { + const contextId = 'contextId'; + const hostName = 'foo'; + + const result = getHostFlyoutPanelProps({ contextId, hostName }); + + expect(result).toEqual({ + id: 'host-panel', + params: { contextID: contextId, hostName, scopeId: 'alerts-page' }, + }); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/get_user_flyout_panel_props.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/get_user_flyout_panel_props.test.ts new file mode 100644 index 0000000000000..92cb21e1f5dee --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/get_user_flyout_panel_props.test.ts @@ -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. + */ + +import { isUserName } from './get_user_flyout_panel_props'; + +describe('getUserFlyoutPanelProps', () => { + describe('isUserName', () => { + it('returns true when fieldName is "user.name"', () => { + const fieldName = 'user.name'; + const result = isUserName(fieldName); + + expect(result).toBe(true); + }); + + it('returns false when fieldName is NOT "user.name"', () => { + const fieldName = 'other.field'; + const result = isUserName(fieldName); + + expect(result).toBe(false); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/helpers.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/helpers.test.ts new file mode 100644 index 0000000000000..e6e001d290afe --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/helpers.test.ts @@ -0,0 +1,58 @@ +/* + * 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 { getFlyoutPanelProps } from './helpers'; + +describe('helpers', () => { + describe('getFlyoutPanelProps', () => { + it('returns FlyoutPanelProps for a valid host name', () => { + const contextId = 'contextId'; + const fieldName = 'host.name'; + const value = 'example.com'; + + const flyoutPanelProps = getFlyoutPanelProps({ contextId, fieldName, value }); + + expect(flyoutPanelProps).toEqual({ + id: 'host-panel', + params: { contextID: contextId, hostName: value, scopeId: 'alerts-page' }, + }); + }); + + it('returns FlyoutPanelProps for a valid user name', () => { + const contextId = 'contextId'; + const fieldName = 'user.name'; + const value = 'administator'; + + const flyoutPanelProps = getFlyoutPanelProps({ contextId, fieldName, value }); + + expect(flyoutPanelProps).toEqual({ + id: 'user-panel', + params: { contextID: contextId, userName: value, scopeId: 'alerts-page' }, + }); + }); + + it('returns null for an unknown field name', () => { + const contextId = 'contextId'; + const fieldName = 'unknown.field'; + const value = 'example'; + + const flyoutPanelProps = getFlyoutPanelProps({ contextId, fieldName, value }); + + expect(flyoutPanelProps).toBeNull(); + }); + + it('returns null when value is not a string', () => { + const contextId = 'contextId'; + const fieldName = 'host.name'; + const value = 123; + + const flyoutPanelProps = getFlyoutPanelProps({ contextId, fieldName, value }); + + expect(flyoutPanelProps).toBeNull(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/index.test.tsx new file mode 100644 index 0000000000000..8f647d02a626f --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/field_markdown_renderer/index.test.tsx @@ -0,0 +1,110 @@ +/* + * 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 { useExpandableFlyoutApi } from '@kbn/expandable-flyout'; +import { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TestProviders } from '../../../common/mock'; +import { getFieldMarkdownRenderer } from '.'; + +jest.mock('@kbn/expandable-flyout', () => ({ + useExpandableFlyoutApi: jest.fn(), +})); + +describe('getFieldMarkdownRenderer', () => { + const mockOpenRightPanel = jest.fn(); + const mockUseExpandableFlyoutApi = useExpandableFlyoutApi as jest.MockedFunction< + typeof useExpandableFlyoutApi + >; + + beforeEach(() => { + jest.clearAllMocks(); + + mockUseExpandableFlyoutApi.mockReturnValue({ + closeFlyout: jest.fn(), + closeLeftPanel: jest.fn(), + closePreviewPanel: jest.fn(), + closeRightPanel: jest.fn(), + previousPreviewPanel: jest.fn(), + openFlyout: jest.fn(), + openLeftPanel: jest.fn(), + openPreviewPanel: jest.fn(), + openRightPanel: mockOpenRightPanel, + }); + }); + + it('renders the field value', () => { + const FieldMarkdownRenderer = getFieldMarkdownRenderer(false); + const icon = ''; + const name = 'some.field'; + const value = 'some.value'; + + render( + + + + ); + + const fieldValue = screen.getByText(value); + + expect(fieldValue).toBeInTheDocument(); + }); + + it('opens the right panel when the entity button is clicked', () => { + const FieldMarkdownRenderer = getFieldMarkdownRenderer(false); + const icon = 'user'; + const name = 'user.name'; + const value = 'some.user'; + + render( + + + + ); + + const entityButton = screen.getByTestId('entityButton'); + + fireEvent.click(entityButton); + + expect(mockOpenRightPanel).toHaveBeenCalledTimes(1); + }); + + it('does NOT render the entity button when flyoutPanelProps is null', () => { + const FieldMarkdownRenderer = getFieldMarkdownRenderer(false); + const icon = ''; + const name = 'some.field'; + const value = 'some.value'; + + render( + + + + ); + + const entityButton = screen.queryByTestId('entityButton'); + + expect(entityButton).not.toBeInTheDocument(); + }); + + it('renders disabled actions badge when disableActions is true', () => { + const FieldMarkdownRenderer = getFieldMarkdownRenderer(true); // disable actions + const icon = 'user'; + const name = 'user.name'; + const value = 'some.user'; + + render( + + + + ); + + const disabledActionsBadge = screen.getByTestId('disabledActionsBadge'); + + expect(disabledActionsBadge).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/index.test.tsx new file mode 100644 index 0000000000000..5013ce646fe28 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_markdown_formatter/index.test.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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TestProviders } from '../../common/mock'; +import { AttackDiscoveryMarkdownFormatter } from '.'; + +describe('AttackDiscoveryMarkdownFormatter', () => { + const markdown = ` + The following attack chain was detected involving Microsoft Office documents on multiple hosts: + +- On {{ host.name 39054a91-67f9-46fa-b9d1-85f928d4cd1b }}, a malicious Microsoft Office document was opened by {{ user.name 2c13d131-8fab-41b9-841e-669c66315a23 }}. +- This document launched a child process to write and execute a malicious script file named "AppPool.vbs". +- The "AppPool.vbs" script then spawned PowerShell to execute an obfuscated script payload from "AppPool.ps1". +- On {{ host.name 5149b291-72d0-4373-93ec-c117477932fe }}, a similar attack involving a malicious Office document and the creation of "AppPool.vbs" was detected and prevented. + +This appears to be a malware attack delivered via spearphishing, likely exploiting a vulnerability in Microsoft Office to gain initial access and then using PowerShell for execution and obfuscation. The attacker employed defense evasion techniques like script obfuscation and system binary proxies like "wscript.exe" and "mshta.exe". Mitigations should focus on patching Office vulnerabilities, restricting script execution, and enhancing email security controls. + `; + + it('renders the expected markdown', () => { + render( + + + + ); + + const result = screen.getByTestId('attackDiscoveryMarkdownFormatter'); + + expect(result).toHaveTextContent( + 'The following attack chain was detected involving Microsoft Office documents on multiple hosts: On 39054a91-67f9-46fa-b9d1-85f928d4cd1b, a malicious Microsoft Office document was opened by 2c13d131-8fab-41b9-841e-669c66315a23. This document launched a child process to write and execute a malicious script file named "AppPool.vbs". The "AppPool.vbs" script then spawned PowerShell to execute an obfuscated script payload from "AppPool.ps1". On 5149b291-72d0-4373-93ec-c117477932fe, a similar attack involving a malicious Office document and the creation of "AppPool.vbs" was detected and prevented. This appears to be a malware attack delivered via spearphishing, likely exploiting a vulnerability in Microsoft Office to gain initial access and then using PowerShell for execution and obfuscation. The attacker employed defense evasion techniques like script obfuscation and system binary proxies like "wscript.exe" and "mshta.exe". Mitigations should focus on patching Office vulnerabilities, restricting script execution, and enhancing email security controls.' + ); + }); + + it('renders interactive host entities', () => { + render( + + + + ); + + const entities = screen.getAllByTestId('entityButton'); + + expect(entities.length).toEqual(3); + }); + + it('renders NON-interactive host entities when disableActions is true', () => { + render( + + + + ); + + const entities = screen.queryAllByTestId('entityButton'); + + expect(entities.length).toEqual(0); // <-- no interactive buttons + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actionable_summary/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actionable_summary/index.test.tsx new file mode 100644 index 0000000000000..55d636bf35270 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actionable_summary/index.test.tsx @@ -0,0 +1,109 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { ActionableSummary } from '.'; +import { TestProviders } from '../../../common/mock'; +import { mockAttackDiscovery } from '../../mock/mock_attack_discovery'; + +describe('ActionableSummary', () => { + const mockReplacements = { + '5e454c38-439c-4096-8478-0a55511c76e3': 'foo.hostname', + '3bdc7952-a334-4d95-8092-cd176546e18a': 'bar.username', + }; + + describe('when entities with replacements are provided', () => { + beforeEach(() => { + render( + + + + ); + }); + + it('renders a hostname with the expected value from replacements', () => { + expect(screen.getAllByTestId('entityButton')[0]).toHaveTextContent('foo.hostname'); + }); + + it('renders a username with the expected value from replacements', () => { + expect(screen.getAllByTestId('entityButton')[1]).toHaveTextContent('bar.username'); + }); + }); + + describe('when entities that do NOT have replacements are provided', () => { + beforeEach(() => { + render( + + + + ); + }); + + it('renders a hostname with with the original hostname value', () => { + expect(screen.getAllByTestId('entityButton')[0]).toHaveTextContent( + '5e454c38-439c-4096-8478-0a55511c76e3' + ); + }); + + it('renders a username with the original username value', () => { + expect(screen.getAllByTestId('entityButton')[1]).toHaveTextContent( + '3bdc7952-a334-4d95-8092-cd176546e18a' + ); + }); + }); + + describe('when showAnonymized is true', () => { + beforeEach(() => { + render( + + + + ); + }); + + it('renders a disabled badge with the original hostname value', () => { + expect(screen.getAllByTestId('disabledActionsBadge')[0]).toHaveTextContent( + '5e454c38-439c-4096-8478-0a55511c76e3' + ); + }); + + it('renders a disabled badge with the original username value', () => { + expect(screen.getAllByTestId('disabledActionsBadge')[1]).toHaveTextContent( + '3bdc7952-a334-4d95-8092-cd176546e18a' + ); + }); + }); + + describe('View in AI assistant', () => { + beforeEach(() => { + render( + + + + ); + }); + + it('renders the View in AI assistant button', () => { + expect(screen.getByTestId('viewInAiAssistantCompact')).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/actions_placeholder/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/actions_placeholder/index.test.tsx new file mode 100644 index 0000000000000..ac2494f050d88 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/actions_placeholder/index.test.tsx @@ -0,0 +1,23 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { ActionsPlaceholder } from '.'; + +describe('ActionsPlaceholder', () => { + beforeEach(() => render()); + + const expectedSkeletonTitles = ['skeletonTitle1', 'skeletonTitle2', 'skeletonTitle3']; + + expectedSkeletonTitles.forEach((expectedSkeletonTitle) => { + it(`renders the ${expectedSkeletonTitle} skeleton title`, () => { + expect(screen.getByTestId(expectedSkeletonTitle)).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/alerts_badge/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/alerts_badge/index.test.tsx new file mode 100644 index 0000000000000..bc45d195aacfa --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/alerts_badge/index.test.tsx @@ -0,0 +1,21 @@ +/* + * 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 { render } from '@testing-library/react'; +import React from 'react'; + +import { AlertsBadge } from '.'; + +describe('AlertsBadge', () => { + it('render the expected alerts count', () => { + const alertsCount = 5; + + const { getByTestId } = render(); + const badgeElement = getByTestId('alertsBadge'); + + expect(badgeElement.textContent).toBe(`${alertsCount}`); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/index.test.tsx new file mode 100644 index 0000000000000..30096f33dde90 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/index.test.tsx @@ -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. + */ + +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Actions } from '.'; +import { TestProviders } from '../../../common/mock'; +import { mockAttackDiscovery } from '../../mock/mock_attack_discovery'; +import { ATTACK_CHAIN, ALERTS } from './translations'; + +describe('Actions', () => { + beforeEach(() => + render( + + + + ) + ); + + it('renders the attack chain label', () => { + expect(screen.getByTestId('attackChainLabel')).toHaveTextContent(ATTACK_CHAIN); + }); + + it('renders the mini attack chain component', () => { + expect(screen.getByTestId('miniAttackChain')).toBeInTheDocument(); + }); + + it('renders the alerts label', () => { + expect(screen.getByTestId('alertsLabel')).toHaveTextContent(ALERTS); + }); + + it('renders the alerts badge with the expected count', () => { + expect(screen.getByTestId('alertsBadge')).toHaveTextContent( + `${mockAttackDiscovery.alertIds.length}` + ); + }); + + it('renders the take action dropdown', () => { + expect(screen.getByTestId('takeAction')).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/helpers.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/helpers.test.ts new file mode 100644 index 0000000000000..9d58a1487d0ca --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/helpers.test.ts @@ -0,0 +1,43 @@ +/* + * 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 { getOriginalAlertIds } from './helpers'; + +describe('helpers', () => { + describe('getOriginalAlertIds', () => { + const alertIds = ['alert1', 'alert2', 'alert3']; + + it('returns the original alertIds when no replacements are provided', () => { + const result = getOriginalAlertIds({ alertIds }); + + expect(result).toEqual(alertIds); + }); + + it('returns the replaced alertIds when replacements are provided', () => { + const replacements = { + alert1: 'replaced1', + alert3: 'replaced3', + }; + const expected = ['replaced1', 'alert2', 'replaced3']; + + const result = getOriginalAlertIds({ alertIds, replacements }); + + expect(result).toEqual(expected); + }); + + it('returns the original alertIds when replacements are provided but no replacement is found', () => { + const replacements = { + alert4: 'replaced4', + alert5: 'replaced5', + }; + + const result = getOriginalAlertIds({ alertIds, replacements }); + + expect(result).toEqual(alertIds); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/index.test.tsx new file mode 100644 index 0000000000000..2772aa6e0c7a2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/take_action/index.test.tsx @@ -0,0 +1,47 @@ +/* + * 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 { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TestProviders } from '../../../../common/mock'; +import { mockAttackDiscovery } from '../../../mock/mock_attack_discovery'; +import { TakeAction } from '.'; + +describe('TakeAction', () => { + beforeEach(() => { + jest.clearAllMocks(); + + render( + + + + ); + + const takeActionButtons = screen.getAllByTestId('takeActionPopoverButton'); + + fireEvent.click(takeActionButtons[0]); // open the popover + }); + + it('renders the Add to new case action', () => { + const addToCase = screen.getByTestId('addToCase'); + + expect(addToCase).toBeInTheDocument(); + }); + + it('renders the Add to existing case action', () => { + const addToCase = screen.getByTestId('addToExistingCase'); + + expect(addToCase).toBeInTheDocument(); + }); + + it('renders the View in AI Assistant action', () => { + const addToCase = screen.getByTestId('viewInAiAssistant'); + + expect(addToCase).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/use_add_to_case/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/use_add_to_case/index.test.tsx new file mode 100644 index 0000000000000..d1c2e84049e9a --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/use_add_to_case/index.test.tsx @@ -0,0 +1,87 @@ +/* + * 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 { act, renderHook } from '@testing-library/react-hooks'; + +import { useAddToNewCase } from '.'; +import { TestProviders } from '../../../../common/mock'; + +jest.mock('../../../../common/lib/kibana', () => ({ + useKibana: jest.fn().mockReturnValue({ + services: { + cases: { + hooks: { + useCasesAddToNewCaseFlyout: jest.fn().mockReturnValue({ + open: jest.fn(), + }), + }, + }, + }, + }), +})); + +describe('useAddToNewCase', () => { + it('disables the action when a user can NOT create and read cases', () => { + const canUserCreateAndReadCases = jest.fn().mockReturnValue(false); + + const { result } = renderHook( + () => + useAddToNewCase({ + canUserCreateAndReadCases, + title: 'Persistent Execution of Malicious Application', + }), + { + wrapper: TestProviders, + } + ); + + expect(result.current.disabled).toBe(true); + }); + + it('enables the action when a user can create and read cases', () => { + const canUserCreateAndReadCases = jest.fn().mockReturnValue(true); + + const { result } = renderHook( + () => + useAddToNewCase({ + canUserCreateAndReadCases, + title: 'Persistent Execution of Malicious Application', + }), + { + wrapper: TestProviders, + } + ); + + expect(result.current.disabled).toBe(false); + }); + + it('calls the onClick callback when provided', () => { + const onClick = jest.fn(); + const canUserCreateAndReadCases = jest.fn().mockReturnValue(true); + + const { result } = renderHook( + () => + useAddToNewCase({ + canUserCreateAndReadCases, + title: 'Persistent Execution of Malicious Application', + onClick, + }), + { + wrapper: TestProviders, + } + ); + + act(() => { + result.current.onAddToNewCase({ + alertIds: ['alert1', 'alert2'], + markdownComments: ['Comment 1', 'Comment 2'], + }); + }); + + expect(onClick).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/use_add_to_existing_case/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/use_add_to_existing_case/index.test.tsx new file mode 100644 index 0000000000000..80245d371f412 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/actions/use_add_to_existing_case/index.test.tsx @@ -0,0 +1,142 @@ +/* + * 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 { act, renderHook } from '@testing-library/react-hooks'; + +import { useAddToExistingCase } from '.'; +import { useKibana } from '../../../../common/lib/kibana'; +import { TestProviders } from '../../../../common/mock'; + +jest.mock('../../../../common/lib/kibana', () => ({ + useKibana: jest.fn().mockReturnValue({ + services: { + cases: { + hooks: { + useCasesAddToExistingCaseModal: jest.fn().mockReturnValue({ + open: jest.fn(), + }), + }, + }, + }, + }), +})); + +describe('useAddToExistingCase', () => { + const mockCanUserCreateAndReadCases = jest.fn(); + const mockOnClick = jest.fn(); + const mockAlertIds = ['alert1', 'alert2']; + const mockMarkdownComments = ['Comment 1', 'Comment 2']; + const mockReplacements = { alert1: 'replacement1', alert2: 'replacement2' }; + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('disables the action when a user can NOT create and read cases', () => { + mockCanUserCreateAndReadCases.mockReturnValue(false); + + const { result } = renderHook( + () => + useAddToExistingCase({ + canUserCreateAndReadCases: mockCanUserCreateAndReadCases, + onClick: mockOnClick, + }), + { + wrapper: TestProviders, + } + ); + + expect(result.current.disabled).toBe(true); + }); + + it('enables the action when a user can create and read cases', () => { + mockCanUserCreateAndReadCases.mockReturnValue(true); + + const { result } = renderHook( + () => + useAddToExistingCase({ + canUserCreateAndReadCases: mockCanUserCreateAndReadCases, + onClick: mockOnClick, + }), + { + wrapper: TestProviders, + } + ); + + expect(result.current.disabled).toBe(false); + }); + + it('calls the openSelectCaseModal function with the expected attachments', () => { + mockCanUserCreateAndReadCases.mockReturnValue(true); + const mockOpenSelectCaseModal = jest.fn(); + (useKibana as jest.Mock).mockReturnValue({ + services: { + cases: { + hooks: { + useCasesAddToExistingCaseModal: jest.fn().mockReturnValue({ + open: mockOpenSelectCaseModal, + }), + }, + }, + }, + }); + + const { result } = renderHook( + () => + useAddToExistingCase({ + canUserCreateAndReadCases: mockCanUserCreateAndReadCases, + onClick: mockOnClick, + }), + { + wrapper: TestProviders, + } + ); + + act(() => { + result.current.onAddToExistingCase({ + alertIds: mockAlertIds, + markdownComments: mockMarkdownComments, + replacements: mockReplacements, + }); + }); + + expect(mockOpenSelectCaseModal).toHaveBeenCalledWith({ + getAttachments: expect.any(Function), + }); + + const getAttachments = mockOpenSelectCaseModal.mock.calls[0][0].getAttachments; + const attachments = getAttachments(); + + expect(attachments).toHaveLength(4); + expect(attachments[0]).toEqual({ + comment: 'Comment 1', + type: 'user', + }); + expect(attachments[1]).toEqual({ + comment: 'Comment 2', + type: 'user', + }); + expect(attachments[2]).toEqual({ + alertId: 'replacement1', // <-- case attachment uses the replacement values + index: '', + rule: { + id: null, + name: null, + }, + type: 'alert', + }); + expect(attachments[3]).toEqual({ + alertId: 'replacement2', + index: '', + rule: { + id: null, + name: null, + }, + type: 'alert', + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/index.test.tsx new file mode 100644 index 0000000000000..d65dd87117ca3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/index.test.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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { AttackDiscoveryPanel } from '.'; +import { TestProviders } from '../../common/mock'; +import { mockAttackDiscovery } from '../mock/mock_attack_discovery'; + +describe('AttackDiscoveryPanel', () => { + it('renders the attack discovery accordion', () => { + render( + + + + ); + + const attackDiscoveryAccordion = screen.getByTestId('attackDiscoveryAccordion'); + + expect(attackDiscoveryAccordion).toBeInTheDocument(); + }); + + it('renders empty accordion content', () => { + render( + + + + ); + + const emptyAccordionContent = screen.getByTestId('emptyAccordionContent'); + + expect(emptyAccordionContent).toBeInTheDocument(); + }); + + it('renders the attack discovery summary', () => { + render( + + + + ); + + const actionableSummary = screen.getByTestId('actionableSummary'); + + expect(actionableSummary).toBeInTheDocument(); + }); + + it('renders the attack discovery tabs panel when accordion is open', () => { + render( + + + + ); + + const attackDiscoveryTabsPanel = screen.getByTestId('attackDiscoveryTabsPanel'); + + expect(attackDiscoveryTabsPanel).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.test.tsx new file mode 100644 index 0000000000000..c505aafa6631b --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/alerts_tab/index.test.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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TestProviders } from '../../../../common/mock'; +import { mockAttackDiscovery } from '../../../mock/mock_attack_discovery'; +import { AlertsTab } from '.'; + +describe('AlertsTab', () => { + it('renders the alerts tab', () => { + render( + + + + ); + + const alertsTab = screen.getByTestId('alertsTab'); + + expect(alertsTab).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.test.tsx new file mode 100644 index 0000000000000..3c05a10a6eb06 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.test.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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { AttackDiscoveryTab } from '.'; +import type { Replacements } from '@kbn/elastic-assistant-common'; +import { TestProviders } from '../../../../common/mock'; +import { mockAttackDiscovery } from '../../../mock/mock_attack_discovery'; +import { ATTACK_CHAIN, DETAILS, SUMMARY } from './translations'; + +describe('AttackDiscoveryTab', () => { + const mockReplacements: Replacements = { + '5e454c38-439c-4096-8478-0a55511c76e3': 'foo.hostname', + '3bdc7952-a334-4d95-8092-cd176546e18a': 'bar.username', + }; + + describe('when showAnonymized is false', () => { + const showAnonymized = false; + + beforeEach(() => + render( + + + + ) + ); + + it('renders the summary using the real host and username', () => { + const markdownFormatters = screen.getAllByTestId('attackDiscoveryMarkdownFormatter'); + const summaryMarkdown = markdownFormatters[0]; + + expect(summaryMarkdown).toHaveTextContent( + 'A multi-stage malware attack was detected on foo.hostname involving bar.username. A suspicious application delivered malware, attempted credential theft, and established persistence.' + ); + }); + + it('renders the details using the real host and username', () => { + const markdownFormatters = screen.getAllByTestId('attackDiscoveryMarkdownFormatter'); + const detailsMarkdown = markdownFormatters[1]; + + expect(detailsMarkdown).toHaveTextContent( + `The following attack progression appears to have occurred on the host foo.hostname involving the user bar.username: A suspicious application named "My Go Application.app" was launched, likely through a malicious download or installation. This application spawned child processes to copy a malicious file named "unix1" to the user's home directory and make it executable. The malicious "unix1" file was then executed, attempting to access the user's login keychain and potentially exfiltrate credentials. The suspicious application also launched the "osascript" utility to display a fake system dialog prompting the user for their password, a technique known as credentials phishing. This appears to be a multi-stage attack involving malware delivery, privilege escalation, credential access, and potentially data exfiltration. The attacker may have used social engineering techniques like phishing to initially compromise the system. The suspicious "My Go Application.app" exhibits behavior characteristic of malware families that attempt to steal user credentials and maintain persistence. Mitigations should focus on removing the malicious files, resetting credentials, and enhancing security controls around application whitelisting, user training, and data protection.` + ); + }); + }); + + describe('when showAnonymized is true', () => { + const showAnonymized = true; + + beforeEach(() => + render( + + + + ) + ); + + it('renders the summary using the anonymized host and username', () => { + const markdownFormatters = screen.getAllByTestId('attackDiscoveryMarkdownFormatter'); + const summaryMarkdown = markdownFormatters[0]; + + expect(summaryMarkdown).toHaveTextContent( + 'A multi-stage malware attack was detected on 5e454c38-439c-4096-8478-0a55511c76e3 involving 3bdc7952-a334-4d95-8092-cd176546e18a. A suspicious application delivered malware, attempted credential theft, and established persistence.' + ); + }); + + it('renders the details using the anonymized host and username', () => { + const markdownFormatters = screen.getAllByTestId('attackDiscoveryMarkdownFormatter'); + const detailsMarkdown = markdownFormatters[1]; + + expect(detailsMarkdown).toHaveTextContent( + `The following attack progression appears to have occurred on the host 5e454c38-439c-4096-8478-0a55511c76e3 involving the user 3bdc7952-a334-4d95-8092-cd176546e18a: A suspicious application named "My Go Application.app" was launched, likely through a malicious download or installation. This application spawned child processes to copy a malicious file named "unix1" to the user's home directory and make it executable. The malicious "unix1" file was then executed, attempting to access the user's login keychain and potentially exfiltrate credentials. The suspicious application also launched the "osascript" utility to display a fake system dialog prompting the user for their password, a technique known as credentials phishing. This appears to be a multi-stage attack involving malware delivery, privilege escalation, credential access, and potentially data exfiltration. The attacker may have used social engineering techniques like phishing to initially compromise the system. The suspicious "My Go Application.app" exhibits behavior characteristic of malware families that attempt to steal user credentials and maintain persistence. Mitigations should focus on removing the malicious files, resetting credentials, and enhancing security controls around application whitelisting, user training, and data protection.` + ); + }); + }); + + describe('common cases', () => { + beforeEach(() => + render( + + + + ) + ); + + it('renders the expected summary title', () => { + const summaryTitle = screen.getByTestId('summaryTitle'); + + expect(summaryTitle).toHaveTextContent(SUMMARY); + }); + + it('renders the expected details title', () => { + const detailsTitle = screen.getByTestId('detailsTitle'); + + expect(detailsTitle).toHaveTextContent(DETAILS); + }); + + it('renders the expected attack chain title', () => { + const attackChainTitle = screen.getByTestId('attackChainTitle'); + + expect(attackChainTitle).toHaveTextContent(ATTACK_CHAIN); + }); + + it('renders the attack chain', () => { + const attackChain = screen.getByTestId('attackChain'); + + expect(attackChain).toBeInTheDocument(); + }); + + it('renders the "View in AI Assistant" button', () => { + const viewInAiAssistantButton = screen.getByTestId('viewInAiAssistant'); + + expect(viewInAiAssistantButton).toBeInTheDocument(); + }); + + it('renders the "Investigate in Timeline" button', () => { + const investigateInTimelineButton = screen.getByTestId('investigateInTimelineButton'); + + expect(investigateInTimelineButton).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx index bd36a047c5a1b..23a63d0503db3 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/attack_discovery_tab/index.tsx @@ -85,7 +85,7 @@ const AttackDiscoveryTabComponent: React.FC = ({ {tacticMetadata.length > 0 && ( <> - +

{i18n.ATTACK_CHAIN}

diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.test.tsx new file mode 100644 index 0000000000000..d002c0bde5324 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.test.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 type { Replacements } from '@kbn/elastic-assistant-common'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { getTabs } from './get_tabs'; +import { TestProviders } from '../../../common/mock'; +import { mockAttackDiscovery } from '../../mock/mock_attack_discovery'; +import { ALERTS, ATTACK_DISCOVERY } from './translations'; + +describe('getTabs', () => { + const mockReplacements: Replacements = { + '5e454c38-439c-4096-8478-0a55511c76e3': 'foo.hostname', + '3bdc7952-a334-4d95-8092-cd176546e18a': 'bar.username', + }; + + const tabs = getTabs({ + attackDiscovery: mockAttackDiscovery, + replacements: mockReplacements, + }); + + describe('Attack discovery tab', () => { + const attackDiscoveryTab = tabs.find((tab) => tab.id === 'attackDiscovery--id'); + + it('includes the Attack discovery tab', () => { + expect(attackDiscoveryTab).not.toBeUndefined(); + }); + + it('has the expected tab name', () => { + expect(attackDiscoveryTab?.name).toEqual(ATTACK_DISCOVERY); + }); + + it('renders the expected content', () => { + render({attackDiscoveryTab?.content}); + + expect(screen.getByTestId('attackDiscoveryTab')).toBeInTheDocument(); + }); + }); + + describe('Alerts tab', () => { + const alertsTab = tabs.find((tab) => tab.id === 'alerts--id'); + + it('includes the Alerts tab', () => { + expect(alertsTab).not.toBeUndefined(); + }); + + it('has the expected tab name', () => { + expect(alertsTab?.name).toEqual(ALERTS); + }); + + it('renders the expected content', () => { + render({alertsTab?.content}); + + expect(screen.getByTestId('alertsTab')).toBeInTheDocument(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.tsx index 2cf7905b0c3ca..09708d0880c8a 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/get_tabs.tsx @@ -13,7 +13,7 @@ import { AttackDiscoveryTab } from './attack_discovery_tab'; import { AlertsTab } from './alerts_tab'; import * as i18n from './translations'; -interface TabInfo { +export interface TabInfo { content: JSX.Element; id: string; name: string; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/index.test.tsx new file mode 100644 index 0000000000000..3b155d704708c --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/tabs/index.test.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 { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Tabs } from '.'; +import { TestProviders } from '../../../common/mock'; +import { mockAttackDiscovery } from '../../mock/mock_attack_discovery'; + +describe('Tabs', () => { + beforeEach(() => { + render( + + + + ); + }); + + it('renders the attack discovery tab', () => { + const attackDiscoveryTab = screen.getByTestId('attackDiscoveryTab'); + + expect(attackDiscoveryTab).toBeInTheDocument(); + }); + + it("renders the alerts tab when it's selected", () => { + const alertsTabButton = screen.getByText('Alerts'); + + fireEvent.click(alertsTabButton); + const alertsTab = screen.getByTestId('alertsTab'); + + expect(alertsTab).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/title/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/title/index.test.tsx new file mode 100644 index 0000000000000..8648d861b0352 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/title/index.test.tsx @@ -0,0 +1,36 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Title } from '.'; + +describe('Title', () => { + const title = 'Malware Delivery and Credentials Access on macOS'; + + it('renders the assistant avatar', () => { + render(); + const assistantAvatar = screen.getByTestId('assistantAvatar'); + + expect(assistantAvatar).toBeInTheDocument(); + }); + + it('renders the expected title', () => { + render(<Title isLoading={false} title={title} />); + const titleText = screen.getByTestId('titleText'); + + expect(titleText).toHaveTextContent(title); + }); + + it('renders the skeleton title when isLoading is true', () => { + render(<Title isLoading={true} title={title} />); + const skeletonTitle = screen.getByTestId('skeletonTitle'); + + expect(skeletonTitle).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/index.test.tsx new file mode 100644 index 0000000000000..322e26cb4df48 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/index.test.tsx @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { ViewInAiAssistant } from '.'; +import { TestProviders } from '../../../common/mock'; +import { mockAttackDiscovery } from '../../mock/mock_attack_discovery'; +import { VIEW_IN_AI_ASSISTANT } from './translations'; + +describe('ViewInAiAssistant', () => { + it('renders the assistant avatar', () => { + render( + <TestProviders> + <ViewInAiAssistant attackDiscovery={mockAttackDiscovery} /> + </TestProviders> + ); + + const assistantAvatar = screen.getByTestId('assistantAvatar'); + + expect(assistantAvatar).toBeInTheDocument(); + }); + + it('renders the expected button label', () => { + render( + <TestProviders> + <ViewInAiAssistant attackDiscovery={mockAttackDiscovery} /> + </TestProviders> + ); + + const viewInAiAssistantLabel = screen.getByTestId('viewInAiAssistantLabel'); + + expect(viewInAiAssistantLabel).toHaveTextContent(VIEW_IN_AI_ASSISTANT); + }); + + describe('compact mode', () => { + it('does NOT render the assistant avatar', () => { + render( + <TestProviders> + <ViewInAiAssistant attackDiscovery={mockAttackDiscovery} compact={true} /> + </TestProviders> + ); + + const assistantAvatar = screen.queryByTestId('assistantAvatar'); + + expect(assistantAvatar).not.toBeInTheDocument(); + }); + + it('renders the expected button text', () => { + render( + <TestProviders> + <ViewInAiAssistant attackDiscovery={mockAttackDiscovery} compact={true} /> + </TestProviders> + ); + + const viewInAiAssistantCompact = screen.getByTestId('viewInAiAssistantCompact'); + + expect(viewInAiAssistantCompact).toHaveTextContent(VIEW_IN_AI_ASSISTANT); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.test.ts new file mode 100644 index 0000000000000..cc7058c8f3fe6 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/attack_discovery_panel/view_in_ai_assistant/use_view_in_ai_assistant.test.ts @@ -0,0 +1,86 @@ +/* + * 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 { renderHook } from '@testing-library/react-hooks'; +import { useAssistantOverlay } from '@kbn/elastic-assistant'; + +import { useAssistantAvailability } from '../../../assistant/use_assistant_availability'; +import { getAttackDiscoveryMarkdown } from '../../get_attack_discovery_markdown/get_attack_discovery_markdown'; +import { mockAttackDiscovery } from '../../mock/mock_attack_discovery'; +import { useViewInAiAssistant } from './use_view_in_ai_assistant'; + +jest.mock('@kbn/elastic-assistant'); +jest.mock('../../../assistant/use_assistant_availability'); +jest.mock('../../get_attack_discovery_markdown/get_attack_discovery_markdown'); + +describe('useViewInAiAssistant', () => { + beforeEach(() => { + jest.clearAllMocks(); + + (useAssistantOverlay as jest.Mock).mockReturnValue({ + promptContextId: 'prompt-context-id', + showAssistantOverlay: jest.fn(), + }); + + (useAssistantAvailability as jest.Mock).mockReturnValue({ + hasAssistantPrivilege: true, + isAssistantEnabled: true, + }); + + (getAttackDiscoveryMarkdown as jest.Mock).mockResolvedValue('Test markdown'); + }); + + it('returns the expected promptContextId', () => { + const { result } = renderHook(() => + useViewInAiAssistant({ + attackDiscovery: mockAttackDiscovery, + }) + ); + + expect(result.current.promptContextId).toBe('prompt-context-id'); + }); + + it('returns disabled: false when the user has assistant privileges and promptContextId is provided', () => { + const { result } = renderHook(() => + useViewInAiAssistant({ + attackDiscovery: mockAttackDiscovery, + }) + ); + + expect(result.current.disabled).toBe(false); + }); + + it('returns disabled: true when the user does NOT have assistant privileges', () => { + (useAssistantAvailability as jest.Mock).mockReturnValue({ + hasAssistantPrivilege: false, // <-- the user does NOT have assistant privileges + isAssistantEnabled: true, + }); + + const { result } = renderHook(() => + useViewInAiAssistant({ + attackDiscovery: mockAttackDiscovery, + }) + ); + + expect(result.current.disabled).toBe(true); + }); + + it('returns disabled: true when promptContextId is null', () => { + (useAssistantOverlay as jest.Mock).mockReturnValue({ + promptContextId: null, // <-- promptContextId is null + showAssistantOverlay: jest.fn(), + }); + + const { result } = renderHook(() => + useViewInAiAssistant({ + attackDiscovery: mockAttackDiscovery, + }) + ); + + expect(result.current.disabled).toBe(true); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/get_attack_discovery_markdown/get_attack_discovery_markdown.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/get_attack_discovery_markdown/get_attack_discovery_markdown.test.tsx new file mode 100644 index 0000000000000..4af83edba69aa --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/get_attack_discovery_markdown/get_attack_discovery_markdown.test.tsx @@ -0,0 +1,188 @@ +/* + * 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 { + getAttackChainMarkdown, + getAttackDiscoveryMarkdown, + getMarkdownFields, + getMarkdownWithOriginalValues, +} from './get_attack_discovery_markdown'; +import { mockAttackDiscovery } from '../mock/mock_attack_discovery'; + +describe('getAttackDiscoveryMarkdown', () => { + describe('getMarkdownFields', () => { + it('replaces markdown fields with formatted values', () => { + const markdown = 'This is a {{ field1 value1 }} and {{ field2 value2 }}.'; + const expected = 'This is a `value1` and `value2`.'; + + const result = getMarkdownFields(markdown); + + expect(result).toBe(expected); + }); + + it('handles multiple occurrences of markdown fields', () => { + const markdown = + 'This is a {{ field1 value1 }} and {{ field2 value2 }}. Also, {{ field1 value3 }}.'; + const expected = 'This is a `value1` and `value2`. Also, `value3`.'; + + const result = getMarkdownFields(markdown); + + expect(result).toBe(expected); + }); + + it('handles markdown fields with no spaces around them', () => { + const markdown = 'This is a {{field1 value1}} and {{field2 value2}}.'; + const expected = 'This is a `value1` and `value2`.'; + + const result = getMarkdownFields(markdown); + + expect(result).toBe(expected); + }); + + it('handles empty markdown', () => { + const markdown = ''; + const expected = ''; + + const result = getMarkdownFields(markdown); + + expect(result).toBe(expected); + }); + }); + + describe('getAttackChainMarkdown', () => { + it('returns an empty string when no tactics are detected', () => { + const noTactics = { + ...mockAttackDiscovery, + mitreAttackTactics: [], + }; + + const result = getAttackChainMarkdown(noTactics); + + expect(result).toBe(''); + }); + + it('returns the expected attack chain markdown when tactics are detected', () => { + const result = getAttackChainMarkdown(mockAttackDiscovery); + + expect(result).toBe(`### Attack Chain +- Initial Access +- Execution +- Persistence +- Privilege Escalation +`); + }); + }); + + describe('getMarkdownWithOriginalValues', () => { + const markdown = mockAttackDiscovery.summaryMarkdown; + + it('returns the same markdown when no replacements are provided', () => { + const result = getMarkdownWithOriginalValues({ markdown }); + + expect(result).toBe(markdown); + }); + + it('replaces the UUIDs with the original values when replacements are provided ', () => { + const replacements = { + '5e454c38-439c-4096-8478-0a55511c76e3': 'foo.hostname', + '3bdc7952-a334-4d95-8092-cd176546e18a': 'bar.username', + }; + const expected = + 'A multi-stage malware attack was detected on {{ host.name foo.hostname }} involving {{ user.name bar.username }}. A suspicious application delivered malware, attempted credential theft, and established persistence.'; + + const result = getMarkdownWithOriginalValues({ markdown, replacements }); + + expect(result).toBe(expected); + }); + + it('only replaces values when there are corresponding entries in the replacements', () => { + // The UUID '3bdc7952-a334-4d95-8092-cd176546e18a' is not in the replacements: + const replacements = { + '5e454c38-439c-4096-8478-0a55511c76e3': 'foo.hostname', + }; + + const expected = + 'A multi-stage malware attack was detected on {{ host.name foo.hostname }} involving {{ user.name 3bdc7952-a334-4d95-8092-cd176546e18a }}. A suspicious application delivered malware, attempted credential theft, and established persistence.'; + + const result = getMarkdownWithOriginalValues({ markdown, replacements }); + + expect(result).toBe(expected); + }); + }); + + describe('getAttackDiscoveryMarkdown', () => { + it('returns the expected markdown when replacements are NOT provided', () => { + const expectedMarkdown = `## Malware Attack With Credential Theft Attempt + +Suspicious activity involving the host \`5e454c38-439c-4096-8478-0a55511c76e3\` and user \`3bdc7952-a334-4d95-8092-cd176546e18a\`. + +### Summary +A multi-stage malware attack was detected on \`5e454c38-439c-4096-8478-0a55511c76e3\` involving \`3bdc7952-a334-4d95-8092-cd176546e18a\`. A suspicious application delivered malware, attempted credential theft, and established persistence. + +### Details +The following attack progression appears to have occurred on the host \`5e454c38-439c-4096-8478-0a55511c76e3\` involving the user \`3bdc7952-a334-4d95-8092-cd176546e18a\`: + +- A suspicious application named "My Go Application.app" was launched, likely through a malicious download or installation. +- This application spawned child processes to copy a malicious file named "unix1" to the user's home directory and make it executable. +- The malicious "unix1" file was then executed, attempting to access the user's login keychain and potentially exfiltrate credentials. +- The suspicious application also launched the "osascript" utility to display a fake system dialog prompting the user for their password, a technique known as credentials phishing. + +This appears to be a multi-stage attack involving malware delivery, privilege escalation, credential access, and potentially data exfiltration. The attacker may have used social engineering techniques like phishing to initially compromise the system. The suspicious "My Go Application.app" exhibits behavior characteristic of malware families that attempt to steal user credentials and maintain persistence. Mitigations should focus on removing the malicious files, resetting credentials, and enhancing security controls around application whitelisting, user training, and data protection. + +### Attack Chain +- Initial Access +- Execution +- Persistence +- Privilege Escalation + +`; + + const markdown = getAttackDiscoveryMarkdown({ attackDiscovery: mockAttackDiscovery }); + + expect(markdown).toBe(expectedMarkdown); + }); + + it('returns the expected markdown when replacements are provided', () => { + const replacements = { + '5e454c38-439c-4096-8478-0a55511c76e3': 'foo.hostname', + '3bdc7952-a334-4d95-8092-cd176546e18a': 'bar.username', + }; + + const expectedMarkdown = `## Malware Attack With Credential Theft Attempt + +Suspicious activity involving the host \`foo.hostname\` and user \`bar.username\`. + +### Summary +A multi-stage malware attack was detected on \`foo.hostname\` involving \`bar.username\`. A suspicious application delivered malware, attempted credential theft, and established persistence. + +### Details +The following attack progression appears to have occurred on the host \`foo.hostname\` involving the user \`bar.username\`: + +- A suspicious application named "My Go Application.app" was launched, likely through a malicious download or installation. +- This application spawned child processes to copy a malicious file named "unix1" to the user's home directory and make it executable. +- The malicious "unix1" file was then executed, attempting to access the user's login keychain and potentially exfiltrate credentials. +- The suspicious application also launched the "osascript" utility to display a fake system dialog prompting the user for their password, a technique known as credentials phishing. + +This appears to be a multi-stage attack involving malware delivery, privilege escalation, credential access, and potentially data exfiltration. The attacker may have used social engineering techniques like phishing to initially compromise the system. The suspicious "My Go Application.app" exhibits behavior characteristic of malware families that attempt to steal user credentials and maintain persistence. Mitigations should focus on removing the malicious files, resetting credentials, and enhancing security controls around application whitelisting, user training, and data protection. + +### Attack Chain +- Initial Access +- Execution +- Persistence +- Privilege Escalation + +`; + + const markdown = getAttackDiscoveryMarkdown({ + attackDiscovery: mockAttackDiscovery, + replacements, + }); + + expect(markdown).toBe(expectedMarkdown); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/helpers.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/helpers.test.tsx new file mode 100644 index 0000000000000..4f5e43323333f --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/helpers.test.tsx @@ -0,0 +1,96 @@ +/* + * 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 { + COMMAND_AND_CONTROL, + DISCOVERY, + EXECUTION, + EXFILTRATION, + getTacticLabel, + getTacticMetadata, + INITIAL_ACCESS, + LATERAL_MOVEMENT, + PERSISTENCE, + PRIVILEGE_ESCALATION, + RECONNAISSANCE, + replaceNewlineLiterals, +} from './helpers'; +import { mockAttackDiscovery } from './mock/mock_attack_discovery'; +import * as i18n from './translations'; + +const expectedTactics = { + [RECONNAISSANCE]: i18n.RECONNAISSANCE, + [INITIAL_ACCESS]: i18n.INITIAL_ACCESS, + [EXECUTION]: i18n.EXECUTION, + [PERSISTENCE]: i18n.PERSISTENCE, + [PRIVILEGE_ESCALATION]: i18n.PRIVILEGE_ESCALATION, + [DISCOVERY]: i18n.DISCOVERY, + [LATERAL_MOVEMENT]: i18n.LATERAL_MOVEMENT, + [COMMAND_AND_CONTROL]: i18n.COMMAND_AND_CONTROL, + [EXFILTRATION]: i18n.EXFILTRATION, + unknown: 'unknown', +}; + +describe('helpers', () => { + describe('getTacticLabel', () => { + Object.entries(expectedTactics).forEach(([tactic, expectedLabel]) => { + it(`returns the expected label for ${tactic}`, () => { + const label = getTacticLabel(tactic); + + expect(label).toBe(expectedLabel); + }); + }); + }); + + describe('getTacticMetadata', () => { + const expectedDetected = ['Initial Access', 'Execution', 'Persistence', 'Privilege Escalation']; + + expectedDetected.forEach((tactic) => { + it(`sets the detected property to true for the '${tactic}' tactic`, () => { + const result = getTacticMetadata(mockAttackDiscovery); + const metadata = result.find(({ name }) => name === tactic); + + expect(metadata?.detected).toBe(true); + }); + }); + + it('sets the detected property to false for all tactics that were not detected', () => { + const result = getTacticMetadata(mockAttackDiscovery); + const filtered = result.filter(({ name }) => !expectedDetected.includes(name)); + + filtered.forEach((metadata) => { + expect(metadata.detected).toBe(false); + }); + }); + + it('sets the expected "index" property for each tactic', () => { + const result = getTacticMetadata(mockAttackDiscovery); + + result.forEach((metadata, i) => { + expect(metadata.index).toBe(i); + }); + }); + }); + + describe('replaceNewlineLiterals', () => { + it('replaces multiple newline literals with actual newlines', () => { + const input = 'Multiple\\nnewline\\nliterals'; + const expected = 'Multiple\nnewline\nliterals'; + + const result = replaceNewlineLiterals(input); + + expect(result).toEqual(expected); + }); + + it('does NOT replace anything if there are no newline literals', () => { + const input = 'This is a string without newlines'; + const result = replaceNewlineLiterals(input); + + expect(result).toEqual(input); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/helpers.ts b/x-pack/plugins/security_solution/public/attack_discovery/helpers.ts index 731f1985c7b13..aa56835d5a1ed 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/helpers.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/helpers.ts @@ -56,7 +56,7 @@ export const getTacticLabel = (tactic: string): string => { } }; -interface TacticMetadata { +export interface TacticMetadata { detected: boolean; index: number; name: string; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_attack_discovery.ts b/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_attack_discovery.ts new file mode 100644 index 0000000000000..d5de6e8d7cc06 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_attack_discovery.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. + */ + +import type { AttackDiscovery } from '@kbn/elastic-assistant-common'; + +export const mockAttackDiscovery: AttackDiscovery = { + alertIds: [ + '639801cdb10a93610be4a91fe0eac94cd3d4d292cf0c2a6d7b3674d7f7390357', + 'bdcf649846dc3ed0ca66537e1c1dc62035a35a208ba4d9853a93e9be4b0dbea3', + 'cdbd13134bbd371cd045e5f89970b21ab866a9c3817b2aaba8d8e247ca88b823', + '58571e1653b4201c4f35d49b6eb4023fc0219d5885ff7c385a9253a692a77104', + '06fcb3563de7dad14137c0bb4e5bae17948c808b8a3b8c60d9ec209a865b20ed', + '8bd3fcaeca5698ee26df402c8bc40df0404d34a278bc0bd9355910c8c92a4aee', + '59ff4efa1a03b0d1cb5c0640f5702555faf5c88d273616c1b6e22dcfc47ac46c', + 'f352f8ca14a12062cde77ff2b099202bf74f4a7d757c2ac75ac63690b2f2f91a', + ], + detailsMarkdown: + 'The following attack progression appears to have occurred on the host {{ host.name 5e454c38-439c-4096-8478-0a55511c76e3 }} involving the user {{ user.name 3bdc7952-a334-4d95-8092-cd176546e18a }}:\n\n- A suspicious application named "My Go Application.app" was launched, likely through a malicious download or installation.\n- This application spawned child processes to copy a malicious file named "unix1" to the user\'s home directory and make it executable.\n- The malicious "unix1" file was then executed, attempting to access the user\'s login keychain and potentially exfiltrate credentials.\n- The suspicious application also launched the "osascript" utility to display a fake system dialog prompting the user for their password, a technique known as credentials phishing.\n\nThis appears to be a multi-stage attack involving malware delivery, privilege escalation, credential access, and potentially data exfiltration. The attacker may have used social engineering techniques like phishing to initially compromise the system. The suspicious "My Go Application.app" exhibits behavior characteristic of malware families that attempt to steal user credentials and maintain persistence. Mitigations should focus on removing the malicious files, resetting credentials, and enhancing security controls around application whitelisting, user training, and data protection.', + entitySummaryMarkdown: + 'Suspicious activity involving the host {{ host.name 5e454c38-439c-4096-8478-0a55511c76e3 }} and user {{ user.name 3bdc7952-a334-4d95-8092-cd176546e18a }}.', + id: 'e6d1f8ef-7c1d-42d6-ba6a-11610bab72b1', + mitreAttackTactics: [ + 'Initial Access', + 'Execution', + 'Persistence', + 'Privilege Escalation', + 'Credential Access', + ], + summaryMarkdown: + 'A multi-stage malware attack was detected on {{ host.name 5e454c38-439c-4096-8478-0a55511c76e3 }} involving {{ user.name 3bdc7952-a334-4d95-8092-cd176546e18a }}. A suspicious application delivered malware, attempted credential theft, and established persistence.', + timestamp: '2024-06-25T21:14:40.098Z', + title: 'Malware Attack With Credential Theft Attempt', +}; diff --git a/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_use_attack_discovery.ts b/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_use_attack_discovery.ts index 617f599e09c8f..4f8be970f40a1 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_use_attack_discovery.ts +++ b/x-pack/plugins/security_solution/public/attack_discovery/mock/mock_use_attack_discovery.ts @@ -195,3 +195,87 @@ export const getMockUseAttackDiscoveriesWithNoAttackDiscoveriesLoading = ( replacements: {}, isLoading: true, // <-- attack discoveries are being generated }); + +export const getRawAttackDiscoveryResponse = () => ({ + alertsContextCount: 20, + attackDiscoveries: [ + { + alertIds: [ + '382d546a7ba5ab35c050f106bece236e87e3d51076a479f0beae8b2015b8fb26', + 'ca9da6b3b77b7038d958b9e144f0a406c223a862c0c991ce9782b98e03a98c87', + '5301f4fb014538df7ce1eb9929227dde3adc0bf5b4f28aa15c8aa4e4fda95f35', + '1459af4af8b92e1710c0ee075b1c444eaa927583dfd71b42e9a10de37c8b9cf0', + '468457e9c5132aadae501b75ec5b766e1465ab865ad8d79e03f66593a76fccdf', + 'fb92e7fa5679db3e91d84d998faddb7ed269f1c8cdc40443f35e67c930383d34', + '03e0f8f1598018da8143bba6b60e6ddea30551a2286ba76d717568eed3d17a66', + '28021a7aca7de03018d820182c9784f8d5f2e1b99e0159177509a69bee1c3ac0', + ], + detailsMarkdown: + 'The following attack progression appears to have occurred on the host {{ host.name 05207978-1585-4e46-9b36-69c4bb85a768 }} involving the user {{ user.name ddc8db29-46eb-44fe-80b6-1ea642c338ac }}:\\n\\n- A suspicious application named "My Go Application.app" was launched, likely through a malicious download or installation\\n- This application attempted to run various malicious scripts and commands, including:\\n - Spawning a child process to run the "osascript" utility to display a fake system dialog prompting for user credentials ({{ process.command_line osascript -e display dialog "MacOS wants to access System Preferences\\n\\t\\t\\nPlease enter your password." with title "System Preferences" with icon file "System:Library:CoreServices:CoreTypes.bundle:Contents:Resources:ToolbarAdvanced.icns" default answer "" giving up after 30 with hidden answer ¬ }})\\n - Modifying permissions on a suspicious file named "unix1" ({{ process.command_line chmod 777 /Users/james/unix1 }})\\n - Executing the suspicious "unix1" file and passing it the user\'s login keychain file and a hardcoded password ({{ process.command_line /Users/james/unix1 /Users/james/library/Keychains/login.keychain-db TempTemp1234!! }})\\n\\nThis appears to be a multi-stage malware attack, potentially aimed at credential theft and further malicious execution on the compromised host. The tactics used align with Credential Access ({{ threat.tactic.name Credential Access }}) and Execution ({{ threat.tactic.name Execution }}) based on MITRE ATT&CK.', + entitySummaryMarkdown: + 'Suspicious activity detected on {{ host.name 05207978-1585-4e46-9b36-69c4bb85a768 }} involving {{ user.name ddc8db29-46eb-44fe-80b6-1ea642c338ac }}.', + mitreAttackTactics: ['Credential Access', 'Execution'], + summaryMarkdown: + 'A multi-stage malware attack was detected on a macOS host, likely initiated through a malicious application download. The attack involved credential phishing attempts, suspicious file modifications, and the execution of untrusted binaries potentially aimed at credential theft. {{ host.name 05207978-1585-4e46-9b36-69c4bb85a768 }} and {{ user.name ddc8db29-46eb-44fe-80b6-1ea642c338ac }} were involved.', + title: 'Credential Theft Malware Attack on macOS', + }, + { + alertIds: [ + '8772effc4970e371a26d556556f68cb8c73f9d9d9482b7f20ee1b1710e642a23', + '63c761718211fa51ea797669d845c3d4f23b1a28c77a101536905e6fd0b4aaa6', + '55f4641a9604e1088deae4897e346e63108bde9167256c7cb236164233899dcc', + 'eaf9991c83feef7798983dc7cacda86717d77136a3a72c9122178a03ce2f15d1', + 'f7044f707ac119256e5a0ccd41d451b51bca00bdc6899c7e5e8e1edddfeb6774', + 'fad83b4223f3c159646ad22df9877b9c400f9472655e49781e2a5951b641088e', + ], + detailsMarkdown: + 'The following attack progression appears to have occurred on the host {{ host.name b775910b-4b71-494d-bfb1-4be3fe88c2b0 }} involving the user {{ user.name e411fe2e-aeea-44b5-b09a-4336dabb3969 }}:\\n\\n- A malicious Microsoft Office document was opened, spawning a child process to write a suspicious VBScript file named "AppPool.vbs" ({{ file.path C:\\ProgramData\\WindowsAppPool\\AppPool.vbs }})\\n- The VBScript launched PowerShell and executed an obfuscated script from "AppPool.ps1"\\n- Additional malicious activities were performed, including:\\n - Creating a scheduled task to periodically execute the VBScript\\n - Spawning a cmd.exe process to create the scheduled task\\n - Executing the VBScript directly\\n\\nThis appears to be a multi-stage malware attack initiated through malicious Office documents, employing script obfuscation, scheduled task persistence, and defense evasion tactics. The activities map to Initial Access ({{ threat.tactic.name Initial Access }}), Execution ({{ threat.tactic.name Execution }}), and Defense Evasion ({{ threat.tactic.name Defense Evasion }}) based on MITRE ATT&CK.', + entitySummaryMarkdown: + 'Suspicious activity detected on {{ host.name b775910b-4b71-494d-bfb1-4be3fe88c2b0 }} involving {{ user.name e411fe2e-aeea-44b5-b09a-4336dabb3969 }}.', + mitreAttackTactics: ['Initial Access', 'Execution', 'Defense Evasion'], + summaryMarkdown: + 'A multi-stage malware attack was detected on a Windows host, likely initiated through a malicious Microsoft Office document. The attack involved script obfuscation, scheduled task persistence, and other defense evasion tactics. {{ host.name b775910b-4b71-494d-bfb1-4be3fe88c2b0 }} and {{ user.name e411fe2e-aeea-44b5-b09a-4336dabb3969 }} were involved.', + title: 'Malicious Office Document Initiates Malware Attack', + }, + { + alertIds: [ + 'd1b8b1c6f891fd181af236d0a81b8769c4569016d5b341cdf6a3fefb7cf9cbfd', + '005f2dfb7efb08b34865b308876ecad188fc9a3eebf35b5e3af3c3780a3fb239', + '7e41ddd221831544c5ff805e0ec31fc3c1f22c04257de1366112cfef14df9f63', + ], + detailsMarkdown: + 'The following attack progression appears to have occurred on the host {{ host.name c1e00157-c636-4222-b3a2-5d9ea667a3a8 }} involving the user {{ user.name e411fe2e-aeea-44b5-b09a-4336dabb3969 }}:\\n\\n- A suspicious process launched by msiexec.exe spawned a PowerShell session\\n- The PowerShell process exhibited the following malicious behaviors:\\n - Shellcode injection detected, indicating the presence of the "Windows.Trojan.Bumblebee" malware\\n - Establishing network connections, suggesting command and control or data exfiltration\\n\\nThis appears to be a case of malware delivery and execution via an MSI package, potentially initiated through a software supply chain compromise or social engineering attack. The tactics employed align with Defense Evasion ({{ threat.tactic.name Defense Evasion }}) through system binary proxy execution, as well as potential Command and Control ({{ threat.tactic.name Command and Control }}) based on MITRE ATT&CK.', + entitySummaryMarkdown: + 'Suspicious activity detected on {{ host.name c1e00157-c636-4222-b3a2-5d9ea667a3a8 }} involving {{ user.name e411fe2e-aeea-44b5-b09a-4336dabb3969 }}.', + mitreAttackTactics: ['Defense Evasion', 'Command and Control'], + summaryMarkdown: + 'A malware attack was detected on a Windows host, likely delivered through a compromised MSI package. The attack involved shellcode injection, network connections, and the use of system binaries for defense evasion. {{ host.name c1e00157-c636-4222-b3a2-5d9ea667a3a8 }} and {{ user.name e411fe2e-aeea-44b5-b09a-4336dabb3969 }} were involved.', + title: 'Malware Delivery via Compromised MSI Package', + }, + { + alertIds: [ + '12057d82e79068080f6acf268ca45c777d3f80946b466b59954320ec5f86f24a', + '81c7c57a360bee531b1398b0773e7c4a2332fbdda4e66f135e01fc98ec7f4e3d', + ], + detailsMarkdown: + 'The following attack progression appears to have occurred on the host {{ host.name d4c92b0d-b82f-4702-892d-dd06ad8418e8 }} involving the user {{ user.name 7245f867-9a09-48d7-9165-84a69fa0727d }}:\\n\\n- A malicious file named "kdmtmpflush" with the SHA256 hash {{ file.hash.sha256 74ef6cc38f5a1a80148752b63c117e6846984debd2af806c65887195a8eccc56 }} was copied to the /dev/shm directory\\n- Permissions were modified to make the file executable\\n- The file was then executed with the "--init" argument, likely to initialize malicious components\\n\\nThis appears to be a case of the "Linux.Trojan.BPFDoor" malware being deployed on the Linux host. The tactics employed align with Execution ({{ threat.tactic.name Execution }}) based on MITRE ATT&CK.', + entitySummaryMarkdown: + 'Suspicious activity detected on {{ host.name d4c92b0d-b82f-4702-892d-dd06ad8418e8 }} involving {{ user.name 7245f867-9a09-48d7-9165-84a69fa0727d }}.', + mitreAttackTactics: ['Execution'], + summaryMarkdown: + 'The "Linux.Trojan.BPFDoor" malware was detected being deployed on a Linux host. A malicious file was copied, permissions were modified, and the file was executed to likely initialize malicious components. {{ host.name d4c92b0d-b82f-4702-892d-dd06ad8418e8 }} and {{ user.name 7245f867-9a09-48d7-9165-84a69fa0727d }} were involved.', + title: 'Linux.Trojan.BPFDoor Malware Deployment Detected', + }, + ], + connector_id: 'pmeClaudeV3SonnetUsEast1', + replacements: { + 'ddc8db29-46eb-44fe-80b6-1ea642c338ac': 'james', + '05207978-1585-4e46-9b36-69c4bb85a768': 'SRVMAC08', + '7245f867-9a09-48d7-9165-84a69fa0727d': 'root', + 'e411fe2e-aeea-44b5-b09a-4336dabb3969': 'Administrator', + '5a63f6dc-4e40-41fe-a92c-7898e891025e': 'SRVWIN07-PRIV', + 'b775910b-4b71-494d-bfb1-4be3fe88c2b0': 'SRVWIN07', + 'c1e00157-c636-4222-b3a2-5d9ea667a3a8': 'SRVWIN06', + 'd4c92b0d-b82f-4702-892d-dd06ad8418e8': 'SRVNIX05', + }, +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/animated_counter/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/animated_counter/index.test.tsx new file mode 100644 index 0000000000000..a70bfaa5c9951 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/animated_counter/index.test.tsx @@ -0,0 +1,25 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { AnimatedCounter } from '.'; + +describe('AnimatedCounter', () => { + it('renders the expected final count', async () => { + const animationDurationMs = 10; // ms + const count = 20; + + render(<AnimatedCounter animationDurationMs={animationDurationMs} count={count} />); + await new Promise((resolve) => setTimeout(resolve, animationDurationMs + 10)); + + const animatedCounter = screen.getByTestId('animatedCounter'); + + expect(animatedCounter).toHaveTextContent(`${count}`); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/animated_counter/index.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/animated_counter/index.tsx index 2428158aa5b71..5dd4cb8fc4267 100644 --- a/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/animated_counter/index.tsx +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/animated_counter/index.tsx @@ -11,14 +11,14 @@ import * as d3 from 'd3'; import React, { useRef, useEffect } from 'react'; interface Props { + animationDurationMs?: number; count: number; } -const AnimatedCounterComponent: React.FC<Props> = ({ count }) => { +const AnimatedCounterComponent: React.FC<Props> = ({ animationDurationMs = 1000 * 1, count }) => { const { euiTheme } = useEuiTheme(); const d3Ref = useRef(null); const zero = 0; // counter starts at zero - const animationDurationMs = 1000 * 1; useEffect(() => { if (d3Ref.current) { diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/index.test.tsx new file mode 100644 index 0000000000000..70acc1dbb2ca8 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/empty_prompt/index.test.tsx @@ -0,0 +1,150 @@ +/* + * 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 { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; + +import { EmptyPrompt } from '.'; +import { useAssistantAvailability } from '../../../assistant/use_assistant_availability'; +import { TestProviders } from '../../../common/mock'; + +jest.mock('../../../assistant/use_assistant_availability'); + +describe('EmptyPrompt', () => { + const alertsCount = 20; + const onGenerate = jest.fn(); + + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('when the user has the assistant privilege', () => { + beforeEach(() => { + (useAssistantAvailability as jest.Mock).mockReturnValue({ + hasAssistantPrivilege: true, + isAssistantEnabled: true, + }); + + render( + <TestProviders> + <EmptyPrompt + alertsCount={alertsCount} + isLoading={false} + isDisabled={false} + onGenerate={onGenerate} + /> + </TestProviders> + ); + }); + + it('renders the empty prompt avatar', () => { + const emptyPromptAvatar = screen.getByTestId('emptyPromptAvatar'); + + expect(emptyPromptAvatar).toBeInTheDocument(); + }); + + it('renders the animated counter', () => { + const emptyPromptAnimatedCounter = screen.getByTestId('emptyPromptAnimatedCounter'); + + expect(emptyPromptAnimatedCounter).toBeInTheDocument(); + }); + + it('renders the expected statement', () => { + const emptyPromptAlertsWillBeAnalyzed = screen.getByTestId('emptyPromptAlertsWillBeAnalyzed'); + + expect(emptyPromptAlertsWillBeAnalyzed).toHaveTextContent('alerts will be analyzed'); + }); + + it('calls onGenerate when the generate button is clicked', () => { + const generateButton = screen.getByTestId('generate'); + + fireEvent.click(generateButton); + + expect(onGenerate).toHaveBeenCalled(); + }); + }); + + describe('when the user does NOT have the assistant privilege', () => { + it('disables the generate button when the user does NOT have the assistant privilege', () => { + (useAssistantAvailability as jest.Mock).mockReturnValue({ + hasAssistantPrivilege: false, // <-- the user does NOT have the assistant privilege + isAssistantEnabled: true, + }); + + render( + <TestProviders> + <EmptyPrompt + alertsCount={alertsCount} + isLoading={false} + isDisabled={false} + onGenerate={onGenerate} + /> + </TestProviders> + ); + + const generateButton = screen.getByTestId('generate'); + + expect(generateButton).toBeDisabled(); + }); + }); + + describe('when loading is true', () => { + const isLoading = true; + + beforeEach(() => { + (useAssistantAvailability as jest.Mock).mockReturnValue({ + hasAssistantPrivilege: true, + isAssistantEnabled: true, + }); + + render( + <TestProviders> + <EmptyPrompt + alertsCount={alertsCount} + isLoading={isLoading} + isDisabled={false} + onGenerate={onGenerate} + /> + </TestProviders> + ); + }); + + it('disables the generate button while loading', () => { + const generateButton = screen.getByTestId('generate'); + + expect(generateButton).toBeDisabled(); + }); + }); + + describe('when isDisabled is true', () => { + const isDisabled = true; + + beforeEach(() => { + (useAssistantAvailability as jest.Mock).mockReturnValue({ + hasAssistantPrivilege: true, + isAssistantEnabled: true, + }); + + render( + <TestProviders> + <EmptyPrompt + alertsCount={alertsCount} + isLoading={false} + isDisabled={isDisabled} + onGenerate={onGenerate} + /> + </TestProviders> + ); + }); + + it('disables the generate button when isDisabled is true', () => { + const generateButton = screen.getByTestId('generate'); + + expect(generateButton).toBeDisabled(); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/header/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/header/index.test.tsx new file mode 100644 index 0000000000000..18dddaea3abdc --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/header/index.test.tsx @@ -0,0 +1,183 @@ +/* + * 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 { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Header } from '.'; +import { useAssistantAvailability } from '../../../assistant/use_assistant_availability'; +import { TestProviders } from '../../../common/mock'; + +jest.mock('../../../assistant/use_assistant_availability'); + +describe('Header', () => { + beforeEach(() => { + (useAssistantAvailability as jest.Mock).mockReturnValue({ + hasAssistantPrivilege: true, + isAssistantEnabled: true, + }); + }); + + it('renders the connector selector', () => { + render( + <TestProviders> + <Header + connectorId="testConnectorId" + connectorsAreConfigured={true} + isDisabledActions={false} + isLoading={false} + onCancel={jest.fn()} + onGenerate={jest.fn()} + onConnectorIdSelected={jest.fn()} + /> + </TestProviders> + ); + + const connectorSelector = screen.getByTestId('connectorSelectorPlaceholderButton'); + + expect(connectorSelector).toBeInTheDocument(); + }); + + it('does NOT render the connector selector when connectors are NOT configured', () => { + const connectorsAreConfigured = false; + + render( + <TestProviders> + <Header + connectorId="testConnectorId" + connectorsAreConfigured={connectorsAreConfigured} + isDisabledActions={false} + isLoading={false} + onCancel={jest.fn()} + onGenerate={jest.fn()} + onConnectorIdSelected={jest.fn()} + /> + </TestProviders> + ); + + const connectorSelector = screen.queryByTestId('connectorSelectorPlaceholderButton'); + + expect(connectorSelector).not.toBeInTheDocument(); + }); + + it('invokes onGenerate when the generate button is clicked', () => { + const onGenerate = jest.fn(); + + render( + <TestProviders> + <Header + connectorId="testConnectorId" + connectorsAreConfigured={true} + isDisabledActions={false} + isLoading={false} + onCancel={jest.fn()} + onConnectorIdSelected={jest.fn()} + onGenerate={onGenerate} + /> + </TestProviders> + ); + + const generate = screen.getByTestId('generate'); + + fireEvent.click(generate); + + expect(onGenerate).toHaveBeenCalled(); + }); + + it('disables the generate button when the user does NOT have the assistant privilege', () => { + (useAssistantAvailability as jest.Mock).mockReturnValue({ + hasAssistantPrivilege: false, + isAssistantEnabled: true, + }); + + render( + <TestProviders> + <Header + connectorId="testConnectorId" + connectorsAreConfigured={true} + isDisabledActions={false} + isLoading={false} + onCancel={jest.fn()} + onConnectorIdSelected={jest.fn()} + onGenerate={jest.fn()} + /> + </TestProviders> + ); + + const generate = screen.getByTestId('generate'); + + expect(generate).toBeDisabled(); + }); + + it('displays the cancel button when loading', () => { + const isLoading = true; + + render( + <TestProviders> + <Header + connectorId="testConnectorId" + connectorsAreConfigured={true} + isDisabledActions={false} + isLoading={isLoading} + onCancel={jest.fn()} + onConnectorIdSelected={jest.fn()} + onGenerate={jest.fn()} + /> + </TestProviders> + ); + + const cancel = screen.getByTestId('cancel'); + + expect(cancel).toBeInTheDocument(); + }); + + it('invokes onCancel when the cancel button is clicked', () => { + const isLoading = true; + const onCancel = jest.fn(); + + render( + <TestProviders> + <Header + connectorId="testConnectorId" + connectorsAreConfigured={true} + isDisabledActions={false} + isLoading={isLoading} + onCancel={onCancel} + onConnectorIdSelected={jest.fn()} + onGenerate={jest.fn()} + /> + </TestProviders> + ); + + const cancel = screen.getByTestId('cancel'); + fireEvent.click(cancel); + + expect(onCancel).toHaveBeenCalled(); + }); + + it('disables the generate button when connectorId is undefined', () => { + const connectorId = undefined; + + render( + <TestProviders> + <Header + connectorId={connectorId} + connectorsAreConfigured={true} + isDisabledActions={false} + isLoading={false} + onCancel={jest.fn()} + onConnectorIdSelected={jest.fn()} + onGenerate={jest.fn()} + /> + </TestProviders> + ); + + const generate = screen.getByTestId('generate'); + + expect(generate).toBeDisabled(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.test.tsx new file mode 100644 index 0000000000000..14a707958b888 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/index.test.tsx @@ -0,0 +1,84 @@ +/* + * 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 moment from 'moment'; + +import { act, render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Countdown } from '.'; +import { TestProviders } from '../../../../common/mock'; +import { APPROXIMATE_TIME_REMAINING } from './translations'; +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; + +describe('Countdown', () => { + const connectorIntervals: GenerationInterval[] = [ + { + date: '2024-05-16T14:13:09.838Z', + durationMs: 173648, + }, + { + date: '2024-05-16T13:59:49.620Z', + durationMs: 146605, + }, + { + date: '2024-05-16T13:47:00.629Z', + durationMs: 255163, + }, + ]; + + beforeAll(() => { + jest.useFakeTimers({ legacyFakeTimers: true }); + }); + + beforeEach(() => { + jest.clearAllTimers(); + }); + + afterAll(() => { + jest.useRealTimers(); + }); + + it('returns null when connectorIntervals is empty', () => { + const { container } = render( + <TestProviders> + <Countdown approximateFutureTime={null} connectorIntervals={[]} /> + </TestProviders> + ); + + expect(container.innerHTML).toEqual(''); + }); + + it('renders the expected prefix', () => { + render( + <TestProviders> + <Countdown approximateFutureTime={null} connectorIntervals={connectorIntervals} /> + </TestProviders> + ); + + expect(screen.getByTestId('prefix')).toHaveTextContent(APPROXIMATE_TIME_REMAINING); + }); + + it('renders the expected the timer text', () => { + const approximateFutureTime = moment().add(1, 'minute').toDate(); + + render( + <TestProviders> + <Countdown + approximateFutureTime={approximateFutureTime} + connectorIntervals={connectorIntervals} + /> + </TestProviders> + ); + + act(() => { + jest.runOnlyPendingTimers(); + }); + + expect(screen.getByTestId('timerText')).toHaveTextContent('00:59'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/generation_timing/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/generation_timing/index.test.tsx new file mode 100644 index 0000000000000..35a72d6455f2b --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/generation_timing/index.test.tsx @@ -0,0 +1,40 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { TestProviders } from '../../../../../../common/mock'; +import { GenerationTiming } from '.'; + +describe('GenerationTiming', () => { + const interval = { + connectorId: 'claudeV3SonnetUsEast1', + date: '2024-04-15T13:48:44.397Z', + durationMs: 5000, + }; + + beforeEach(() => { + render( + <TestProviders> + <GenerationTiming interval={interval} /> + </TestProviders> + ); + }); + + it('renders the expected duration in seconds', () => { + const durationText = screen.getByTestId('clockBadge').textContent; + + expect(durationText).toEqual('5s'); + }); + + it('displays the expected date', () => { + const date = screen.getByTestId('date').textContent; + + expect(date).toEqual('Apr 15, 2024 @ 13:48:44.397'); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/helpers.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/helpers.test.ts new file mode 100644 index 0000000000000..6e7b12f0a51c7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/helpers.test.ts @@ -0,0 +1,74 @@ +/* + * 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 moment from 'moment'; + +import { getAverageIntervalSeconds, getTimerPrefix } from './helpers'; +import { APPROXIMATE_TIME_REMAINING, ABOVE_THE_AVERAGE_TIME } from '../translations'; +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; + +describe('helpers', () => { + describe('getAverageIntervalSeconds', () => { + it('returns 0 when the intervals array is empty', () => { + const intervals: GenerationInterval[] = []; + + const average = getAverageIntervalSeconds(intervals); + + expect(average).toEqual(0); + }); + + it('calculates the average interval in seconds', () => { + const intervals: GenerationInterval[] = [ + { + date: '2024-04-15T13:48:44.397Z', + durationMs: 85807, + }, + { + date: '2024-04-15T12:41:15.255Z', + durationMs: 12751, + }, + { + date: '2024-04-12T20:59:13.238Z', + durationMs: 46169, + }, + { + date: '2024-04-12T19:34:56.701Z', + durationMs: 86674, + }, + ]; + + const average = getAverageIntervalSeconds(intervals); + + expect(average).toEqual(57); + }); + }); + + describe('getTimerPrefix', () => { + it('returns APPROXIMATE_TIME_REMAINING when approximateFutureTime is null', () => { + const approximateFutureTime: Date | null = null; + + const result = getTimerPrefix(approximateFutureTime); + + expect(result).toEqual(APPROXIMATE_TIME_REMAINING); + }); + + it('returns APPROXIMATE_TIME_REMAINING when approximateFutureTime is in the future', () => { + const approximateFutureTime = moment().add(1, 'minute').toDate(); + const result = getTimerPrefix(approximateFutureTime); + + expect(result).toEqual(APPROXIMATE_TIME_REMAINING); + }); + + it('returns ABOVE_THE_AVERAGE_TIME when approximateFutureTime is in the past', () => { + const approximateFutureTime = moment().subtract(1, 'minute').toDate(); + + const result = getTimerPrefix(approximateFutureTime); + + expect(result).toEqual(ABOVE_THE_AVERAGE_TIME); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/index.test.tsx new file mode 100644 index 0000000000000..45ea68f2a780c --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/countdown/last_times_popover/index.test.tsx @@ -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. + */ + +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { LastTimesPopover } from '.'; +import { TestProviders } from '../../../../../common/mock'; + +describe('LastTimesPopover', () => { + const connectorIntervals: GenerationInterval[] = [ + { + date: '2024-05-16T14:13:09.838Z', + durationMs: 173648, + }, + { + date: '2024-05-16T13:59:49.620Z', + durationMs: 146605, + }, + { + date: '2024-05-16T13:47:00.629Z', + durationMs: 255163, + }, + ]; + + beforeEach(() => { + render( + <TestProviders> + <LastTimesPopover connectorIntervals={connectorIntervals} /> + </TestProviders> + ); + }); + + it('renders average time calculated message', () => { + const averageTimeIsCalculated = screen.getByTestId('averageTimeIsCalculated'); + + expect(averageTimeIsCalculated).toHaveTextContent( + 'Remaining time is based on the average speed of the last 3 times the same connector generated results.' + ); + }); + + it('renders generation timing for each connector interval', () => { + const generationTimings = screen.getAllByTestId('generationTiming'); + expect(generationTimings.length).toEqual(connectorIntervals.length); + + const expectedDates = [ + 'May 16, 2024 @ 14:13:09.838', + 'May 16, 2024 @ 13:59:49.620', + 'May 16, 2024 @ 13:47:00.629', + ]; + + generationTimings.forEach((timing, i) => expect(timing).toHaveTextContent(expectedDates[i])); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/index.test.tsx new file mode 100644 index 0000000000000..af6efafb3c1dd --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/index.test.tsx @@ -0,0 +1,73 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { LoadingCallout } from '.'; +import type { GenerationInterval } from '@kbn/elastic-assistant-common'; +import { TestProviders } from '../../../common/mock'; + +describe('LoadingCallout', () => { + const connectorIntervals: GenerationInterval[] = [ + { + date: '2024-05-16T14:13:09.838Z', + durationMs: 173648, + }, + { + date: '2024-05-16T13:59:49.620Z', + durationMs: 146605, + }, + { + date: '2024-05-16T13:47:00.629Z', + durationMs: 255163, + }, + ]; + + const defaultProps = { + alertsCount: 30, + approximateFutureTime: new Date(), + connectorIntervals, + }; + + it('renders the animated loading icon', () => { + render( + <TestProviders> + <LoadingCallout {...defaultProps} /> + </TestProviders> + ); + + const loadingElastic = screen.getByTestId('loadingElastic'); + + expect(loadingElastic).toBeInTheDocument(); + }); + + it('renders loading messages with the expected count', () => { + render( + <TestProviders> + <LoadingCallout {...defaultProps} /> + </TestProviders> + ); + + const aisCurrentlyAnalyzing = screen.getByTestId('aisCurrentlyAnalyzing'); + + expect(aisCurrentlyAnalyzing).toHaveTextContent( + 'AI is analyzing up to 30 alerts in the last 24 hours to generate discoveries.' + ); + }); + + it('renders the countdown', () => { + render( + <TestProviders> + <LoadingCallout {...defaultProps} /> + </TestProviders> + ); + const countdown = screen.getByTestId('countdown'); + + expect(countdown).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/info_popover_body/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/info_popover_body/index.test.tsx new file mode 100644 index 0000000000000..b264af94dcb1b --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/info_popover_body/index.test.tsx @@ -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 type { GenerationInterval } from '@kbn/elastic-assistant-common'; +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { InfoPopoverBody } from '.'; +import { TestProviders } from '../../../../common/mock'; +import { AVERAGE_TIME } from '../countdown/translations'; + +describe('InfoPopoverBody', () => { + const connectorIntervals: GenerationInterval[] = [ + { + date: '2024-05-16T14:13:09.838Z', + durationMs: 173648, + }, + { + date: '2024-05-16T13:59:49.620Z', + durationMs: 146605, + }, + { + date: '2024-05-16T13:47:00.629Z', + durationMs: 255163, + }, + ]; + + it('renders the expected average time', () => { + render( + <TestProviders> + <InfoPopoverBody connectorIntervals={connectorIntervals} /> + </TestProviders> + ); + + const averageTimeBadge = screen.getByTestId('averageTimeBadge'); + + expect(averageTimeBadge).toHaveTextContent('191s'); + }); + + it('renders the expected explanation', () => { + render( + <TestProviders> + <InfoPopoverBody connectorIntervals={connectorIntervals} /> + </TestProviders> + ); + + const averageTimeIsCalculated = screen.getAllByTestId('averageTimeIsCalculated'); + + expect(averageTimeIsCalculated[0]).toHaveTextContent(AVERAGE_TIME); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/loading_messages/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/loading_messages/index.test.tsx new file mode 100644 index 0000000000000..250a25055791a --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/loading_callout/loading_messages/index.test.tsx @@ -0,0 +1,43 @@ +/* + * 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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { LoadingMessages } from '.'; +import { TestProviders } from '../../../../common/mock'; +import { ATTACK_DISCOVERY_GENERATION_IN_PROGRESS } from '../translations'; + +describe('LoadingMessages', () => { + it('renders the expected loading message', () => { + render( + <TestProviders> + <LoadingMessages alertsCount={20} /> + </TestProviders> + ); + const attackDiscoveryGenerationInProgress = screen.getByTestId( + 'attackDiscoveryGenerationInProgress' + ); + + expect(attackDiscoveryGenerationInProgress).toHaveTextContent( + ATTACK_DISCOVERY_GENERATION_IN_PROGRESS + ); + }); + + it('renders the loading message with the expected alerts count', () => { + render( + <TestProviders> + <LoadingMessages alertsCount={20} /> + </TestProviders> + ); + const aiCurrentlyAnalyzing = screen.getByTestId('aisCurrentlyAnalyzing'); + + expect(aiCurrentlyAnalyzing).toHaveTextContent( + 'AI is analyzing up to 20 alerts in the last 24 hours to generate discoveries.' + ); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/page_title/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/page_title/index.test.tsx new file mode 100644 index 0000000000000..0c8ea0501f2d3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/page_title/index.test.tsx @@ -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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { PageTitle } from '.'; +import { ATTACK_DISCOVERY_PAGE_TITLE } from './translations'; + +describe('PageTitle', () => { + it('renders the expected title', () => { + render(<PageTitle />); + + const attackDiscoveryPageTitle = screen.getByTestId('attackDiscoveryPageTitle'); + + expect(attackDiscoveryPageTitle).toHaveTextContent(ATTACK_DISCOVERY_PAGE_TITLE); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/summary/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/summary/index.test.tsx new file mode 100644 index 0000000000000..43134b14f616d --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/summary/index.test.tsx @@ -0,0 +1,56 @@ +/* + * 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 { fireEvent, render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Summary } from '.'; + +describe('Summary', () => { + const defaultProps = { + alertsCount: 20, + attackDiscoveriesCount: 5, + lastUpdated: new Date(), + onToggleShowAnonymized: jest.fn(), + showAnonymized: false, + }; + + beforeEach(() => jest.clearAllMocks()); + + it('renders the expected summary counts', () => { + render(<Summary {...defaultProps} />); + + const summaryCount = screen.getByTestId('summaryCount'); + + expect(summaryCount).toHaveTextContent('5 discoveries|20 alerts|Generated: a few seconds ago'); + }); + + it('renders the expected button icon when showAnonymized is false', () => { + render(<Summary {...defaultProps} />); + + const toggleAnonymized = screen.getByTestId('toggleAnonymized').querySelector('span'); + + expect(toggleAnonymized).toHaveAttribute('data-euiicon-type', 'eyeClosed'); + }); + + it('renders the expected button icon when showAnonymized is true', () => { + render(<Summary {...defaultProps} showAnonymized={true} />); + + const toggleAnonymized = screen.getByTestId('toggleAnonymized').querySelector('span'); + + expect(toggleAnonymized).toHaveAttribute('data-euiicon-type', 'eye'); + }); + + it('calls onToggleShowAnonymized when toggle button is clicked', () => { + render(<Summary {...defaultProps} />); + + const toggleAnonymized = screen.getByTestId('toggleAnonymized'); + fireEvent.click(toggleAnonymized); + + expect(defaultProps.onToggleShowAnonymized).toHaveBeenCalled(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/summary_count/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/summary_count/index.test.tsx new file mode 100644 index 0000000000000..b8460eafef87b --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/summary_count/index.test.tsx @@ -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. + */ + +import { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { SummaryCount } from '.'; + +describe('SummaryCount', () => { + const defaultProps = { + alertsCount: 20, + attackDiscoveriesCount: 5, + lastUpdated: new Date(), + }; + + it('renders the expected count of attack discoveries', () => { + render(<SummaryCount {...defaultProps} />); + + const discoveriesCount = screen.getByTestId('discoveriesCount'); + + expect(discoveriesCount).toHaveTextContent('5 discoveries'); + }); + + it('renders the expected alerts count', () => { + render(<SummaryCount {...defaultProps} />); + + const alertsCount = screen.getByTestId('alertsCount'); + + expect(alertsCount).toHaveTextContent('20 alerts'); + }); + + it('renders a humanized last generated when lastUpdated is provided', () => { + render(<SummaryCount {...defaultProps} />); + + const lastGenerated = screen.getByTestId('lastGenerated'); + + expect(lastGenerated).toHaveTextContent('Generated: a few seconds ago'); + }); + + it('should NOT render the last generated date when lastUpdated is null', () => { + render(<SummaryCount {...defaultProps} lastUpdated={null} />); + + const lastGenerated = screen.queryByTestId('lastGenerated'); + + expect(lastGenerated).not.toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/pages/upgrade/index.test.tsx b/x-pack/plugins/security_solution/public/attack_discovery/pages/upgrade/index.test.tsx new file mode 100644 index 0000000000000..e72f53e9062d7 --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/pages/upgrade/index.test.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 { render, screen } from '@testing-library/react'; +import React from 'react'; + +import { Upgrade } from '.'; +import { TestProviders } from '../../../common/mock'; +import { + ATTACK_DISCOVERY_IS_AVAILABLE, + FIND_POTENTIAL_ATTACKS_WITH_AI, + PLEASE_UPGRADE, +} from './translations'; + +describe('Upgrade', () => { + beforeEach(() => { + render( + <TestProviders> + <Upgrade /> + </TestProviders> + ); + }); + + it('renders the assistant avatar', () => { + const assistantAvatar = screen.getByTestId('assistantAvatar'); + + expect(assistantAvatar).toBeInTheDocument(); + }); + + it('renders the expected upgrade title', () => { + const upgradeTitle = screen.getByTestId('upgradeTitle'); + + expect(upgradeTitle).toHaveTextContent(FIND_POTENTIAL_ATTACKS_WITH_AI); + }); + + it('renders the attack discovery availability text', () => { + const attackDiscoveryIsAvailable = screen.getByTestId('attackDiscoveryIsAvailable'); + + expect(attackDiscoveryIsAvailable).toHaveTextContent(ATTACK_DISCOVERY_IS_AVAILABLE); + }); + + it('renders the please upgrade text', () => { + const pleaseUpgrade = screen.getByTestId('pleaseUpgrade'); + + expect(pleaseUpgrade).toHaveTextContent(PLEASE_UPGRADE); + }); + + it('renders the upgrade subscription plans (docs) link', () => { + const upgradeDocs = screen.getByRole('link', { name: 'Subscription plans' }); + + expect(upgradeDocs).toBeInTheDocument(); + }); + + it('renders the upgrade Manage license call to action', () => { + const upgradeCta = screen.getByRole('link', { name: 'Manage license' }); + + expect(upgradeCta).toBeInTheDocument(); + }); +}); diff --git a/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/helpers.test.ts b/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/helpers.test.ts new file mode 100644 index 0000000000000..a15cb7090f6cc --- /dev/null +++ b/x-pack/plugins/security_solution/public/attack_discovery/use_attack_discovery/helpers.test.ts @@ -0,0 +1,284 @@ +/* + * 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 { OpenAiProviderType } from '@kbn/stack-connectors-plugin/public/common'; +import type { ActionConnector } from '@kbn/triggers-actions-ui-plugin/public'; +import { omit } from 'lodash/fp'; + +import { getGenAiConfig, getRequestBody } from './helpers'; + +const connector: ActionConnector = { + actionTypeId: '.gen-ai', + config: { + apiProvider: 'Azure OpenAI', + apiUrl: + 'https://example.com/openai/deployments/example/chat/completions?api-version=2024-02-15-preview', + }, + id: '15b4f8df-e2ca-4060-81a1-3bd2a2bffc7e', + isDeprecated: false, + isMissingSecrets: false, + isPreconfigured: false, + isSystemAction: false, + name: 'Azure OpenAI GPT-4o', + secrets: { secretTextField: 'a secret' }, +}; + +describe('getGenAiConfig', () => { + it('returns undefined when the connector is preconfigured', () => { + const preconfigured = { + ...connector, + isPreconfigured: true, + }; + + const result = getGenAiConfig(preconfigured); + + expect(result).toBeUndefined(); + }); + + it('returns the expected GenAiConfig when the connector is NOT preconfigured', () => { + const result = getGenAiConfig(connector); + + expect(result).toEqual({ + apiProvider: connector.config.apiProvider, + apiUrl: connector.config.apiUrl, + defaultModel: '2024-02-15-preview', + }); + }); + + it('returns the expected defaultModel for Azure OpenAI', () => { + const result = getGenAiConfig(connector); + + expect(result).toEqual({ + apiProvider: connector.config.apiProvider, + apiUrl: connector.config.apiUrl, + defaultModel: '2024-02-15-preview', + }); + }); + + it('returns the an undefined defaultModel for NON-Azure OpenAI when the config does NOT include a default model', () => { + const apiProvider = 'OpenAI'; // <-- NON-Azure OpenAI + const openAiConnector = { + ...connector, + config: { + ...connector.config, + apiProvider, + // config does NOT have a default model + }, + }; + + const result = getGenAiConfig(openAiConnector); + + expect(result).toEqual({ + apiProvider, + apiUrl: connector.config.apiUrl, + defaultModel: undefined, // <-- because the config does not have a default model + }); + }); + + it('returns the expected defaultModel for NON-Azure OpenAi when the config has a default model', () => { + const apiProvider = 'OpenAI'; // <-- NON-Azure OpenAI + const withDefaultModel = { + ...connector, + config: { + ...connector.config, + apiProvider, + defaultModel: 'aDefaultModel', // <-- default model is specified + }, + }; + + const result = getGenAiConfig(withDefaultModel); + + expect(result).toEqual({ + apiProvider, + apiUrl: connector.config.apiUrl, + defaultModel: 'aDefaultModel', + }); + }); + + it('returns the expected GenAiConfig when the connector config is undefined', () => { + const connectorWithoutConfig = omit('config', connector) as ActionConnector< + Record<string, unknown>, + Record<string, unknown> + >; + + const result = getGenAiConfig(connectorWithoutConfig); + + expect(result).toEqual({ + apiProvider: undefined, + apiUrl: undefined, + defaultModel: undefined, + }); + }); +}); + +describe('getRequestBody', () => { + const alertsIndexPattern = 'test-index-pattern'; + const anonymizationFields = { + page: 1, + perPage: 10, + total: 100, + data: [ + { + id: '1', + field: 'field1', + }, + { + id: '2', + field: 'field2', + }, + ], + }; + const knowledgeBase = { + isEnabledKnowledgeBase: true, + isEnabledRAGAlerts: true, + latestAlerts: 20, + }; + const traceOptions = { + apmUrl: '/app/apm', + langSmithProject: '', + langSmithApiKey: '', + }; + + it('returns the expected AttackDiscoveryPostRequestBody', () => { + const result = getRequestBody({ + alertsIndexPattern, + anonymizationFields, + knowledgeBase, + traceOptions, + }); + + expect(result).toEqual({ + alertsIndexPattern, + anonymizationFields: anonymizationFields.data, + apiConfig: { + actionTypeId: '', + connectorId: '', + model: undefined, + provider: undefined, + }, + langSmithProject: undefined, + langSmithApiKey: undefined, + size: knowledgeBase.latestAlerts, + replacements: {}, + subAction: 'invokeAI', + }); + }); + + it('returns the expected AttackDiscoveryPostRequestBody when alertsIndexPattern is undefined', () => { + const result = getRequestBody({ + alertsIndexPattern: undefined, + anonymizationFields, + knowledgeBase, + traceOptions, + }); + + expect(result).toEqual({ + alertsIndexPattern: '', + anonymizationFields: anonymizationFields.data, + apiConfig: { + actionTypeId: '', + connectorId: '', + model: undefined, + provider: undefined, + }, + langSmithProject: undefined, + langSmithApiKey: undefined, + size: knowledgeBase.latestAlerts, + replacements: {}, + subAction: 'invokeAI', + }); + }); + + it('returns the expected AttackDiscoveryPostRequestBody when LangSmith details are provided', () => { + const withLangSmith = { + alertsIndexPattern, + anonymizationFields, + knowledgeBase, + traceOptions: { + apmUrl: '/app/apm', + langSmithProject: 'A project', + langSmithApiKey: 'an API key', + }, + }; + + const result = getRequestBody(withLangSmith); + + expect(result).toEqual({ + alertsIndexPattern, + anonymizationFields: anonymizationFields.data, + apiConfig: { + actionTypeId: '', + connectorId: '', + model: undefined, + provider: undefined, + }, + langSmithApiKey: withLangSmith.traceOptions.langSmithApiKey, + langSmithProject: withLangSmith.traceOptions.langSmithProject, + size: knowledgeBase.latestAlerts, + replacements: {}, + subAction: 'invokeAI', + }); + }); + + it('returns the expected AttackDiscoveryPostRequestBody with the expected apiConfig when selectedConnector is provided', () => { + const result = getRequestBody({ + alertsIndexPattern, + anonymizationFields, + knowledgeBase, + selectedConnector: connector, // <-- selectedConnector is provided + traceOptions, + }); + + expect(result).toEqual({ + alertsIndexPattern, + anonymizationFields: anonymizationFields.data, + apiConfig: { + actionTypeId: connector.actionTypeId, + connectorId: connector.id, + model: undefined, + provider: undefined, + }, + langSmithProject: undefined, + langSmithApiKey: undefined, + size: knowledgeBase.latestAlerts, + replacements: {}, + subAction: 'invokeAI', + }); + }); + + it('returns the expected AttackDiscoveryPostRequestBody with the expected apiConfig when genAiConfig is provided', () => { + const genAiConfig = { + apiProvider: OpenAiProviderType.AzureAi, + defaultModel: '2024-02-15-preview', + }; + + const result = getRequestBody({ + alertsIndexPattern, + anonymizationFields, + genAiConfig, // <-- genAiConfig is provided + knowledgeBase, + selectedConnector: connector, // <-- selectedConnector is provided + traceOptions, + }); + + expect(result).toEqual({ + alertsIndexPattern, + anonymizationFields: anonymizationFields.data, + apiConfig: { + actionTypeId: connector.actionTypeId, + connectorId: connector.id, + model: genAiConfig.defaultModel, + provider: genAiConfig.apiProvider, + }, + langSmithProject: undefined, + langSmithApiKey: undefined, + size: knowledgeBase.latestAlerts, + replacements: {}, + subAction: 'invokeAI', + }); + }); +}); diff --git a/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_anonymized_alerts.test.ts b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_anonymized_alerts.test.ts new file mode 100644 index 0000000000000..6b7526870eb9f --- /dev/null +++ b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_anonymized_alerts.test.ts @@ -0,0 +1,171 @@ +/* + * 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 { elasticsearchServiceMock } from '@kbn/core-elasticsearch-server-mocks'; + +import { getAnonymizedAlerts } from './get_anonymized_alerts'; +import { mockOpenAndAcknowledgedAlertsQueryResults } from '../mock/mock_open_and_acknowledged_alerts_query_results'; +import { getOpenAndAcknowledgedAlertsQuery } from '../open_and_acknowledged_alerts/get_open_and_acknowledged_alerts_query'; +import { MIN_SIZE } from '../open_and_acknowledged_alerts/helpers'; + +jest.mock('../open_and_acknowledged_alerts/get_open_and_acknowledged_alerts_query', () => { + const original = jest.requireActual( + '../open_and_acknowledged_alerts/get_open_and_acknowledged_alerts_query' + ); + + return { + getOpenAndAcknowledgedAlertsQuery: jest.fn(() => original), + }; +}); + +describe('getAnonymizedAlerts', () => { + const alertsIndexPattern = '.alerts-security.alerts-default'; + const mockAnonymizationFields = [ + { + id: '9f95b649-f20e-4edf-bd76-1d21ab6f8e2e', + timestamp: '2024-05-06T22:16:48.489Z', + field: '_id', + allowed: true, + anonymized: false, + createdAt: '2024-05-06T22:16:48.489Z', + namespace: 'default', + }, + { + id: '22f23471-4f6a-4cec-9b2a-cf270ffb53d5', + timestamp: '2024-05-06T22:16:48.489Z', + field: 'host.name', + allowed: true, + anonymized: true, + createdAt: '2024-05-06T22:16:48.489Z', + namespace: 'default', + }, + ]; + const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + const mockReplacements = { + replacement1: 'SRVMAC08', + replacement2: 'SRVWIN01', + replacement3: 'SRVWIN02', + }; + const size = 10; + + beforeEach(() => { + jest.clearAllMocks(); + + (mockEsClient.search as unknown as jest.Mock).mockResolvedValue( + mockOpenAndAcknowledgedAlertsQueryResults + ); + }); + + it('returns an empty array when alertsIndexPattern is not provided', async () => { + const result = await getAnonymizedAlerts({ + esClient: mockEsClient, + size, + }); + + expect(result).toEqual([]); + }); + + it('should return an empty array when size is not provided', async () => { + const result = await getAnonymizedAlerts({ + alertsIndexPattern, + esClient: mockEsClient, + }); + + expect(result).toEqual([]); + }); + + it('should return an empty array when size is out of range', async () => { + const outOfRange = MIN_SIZE - 1; + + const result = await getAnonymizedAlerts({ + alertsIndexPattern, + esClient: mockEsClient, + size: outOfRange, + }); + + expect(result).toEqual([]); + }); + + it('calls getOpenAndAcknowledgedAlertsQuery with the provided anonymizationFields', async () => { + await getAnonymizedAlerts({ + alertsIndexPattern, + anonymizationFields: mockAnonymizationFields, + esClient: mockEsClient, + replacements: mockReplacements, + size, + }); + + expect(getOpenAndAcknowledgedAlertsQuery).toHaveBeenCalledWith({ + alertsIndexPattern, + anonymizationFields: mockAnonymizationFields, + size, + }); + }); + + it('calls getOpenAndAcknowledgedAlertsQuery with empty anonymizationFields when they are NOT provided', async () => { + await getAnonymizedAlerts({ + alertsIndexPattern, + esClient: mockEsClient, + replacements: mockReplacements, + size, + }); + + expect(getOpenAndAcknowledgedAlertsQuery).toHaveBeenCalledWith({ + alertsIndexPattern, + anonymizationFields: [], + size, + }); + }); + + it('returns the expected transformed (anonymized) raw data', async () => { + const result = await getAnonymizedAlerts({ + alertsIndexPattern, + anonymizationFields: mockAnonymizationFields, + esClient: mockEsClient, + replacements: mockReplacements, + size, + }); + + expect(result).toEqual([ + '_id,b6e883c29b32571aaa667fa13e65bbb4f95172a2b84bdfb85d6f16c72b2d2560\nhost.name,replacement1', + '_id,0215a6c5cc9499dd0290cd69a4947efb87d3ddd8b6385a766d122c2475be7367\nhost.name,replacement1', + '_id,600eb9eca925f4c5b544b4e9d3cf95d83b7829f8f74c5bd746369cb4c2968b9a\nhost.name,replacement1', + '_id,e1f4a4ed70190eb4bd256c813029a6a9101575887cdbfa226ac330fbd3063f0c\nhost.name,replacement1', + '_id,2a7a4809ca625dfe22ccd35fbef7a7ba8ed07f109e5cbd17250755cfb0bc615f\nhost.name,replacement1', + '_id,2a9f7602de8656d30dda0ddcf79e78037ac2929780e13d5b2047b3bedc40bb69\nhost.name,replacement1', + '_id,4615c3a90e8057ae5cc9b358bbbf4298e346277a2f068dda052b0b43ef6d5bbd\nhost.name,replacement1', + '_id,449322a72d3f19efbdf983935a1bdd21ebd6b9c761ce31e8b252003017d7e5db\nhost.name,replacement1', + '_id,f465ca9fbfc8bc3b1871e965c9e111cac76ff3f4076fed6bc9da88d49fb43014\nhost.name,replacement3', + '_id,aa283e6a13be77b533eceffb09e48254c8f91feeccc39f7eed80fd3881d053f4\nhost.name,replacement3', + '_id,dd9e4ea23961ccfdb7a9c760ee6bedd19a013beac3b0d38227e7ae77ba4ce515\nhost.name,replacement3', + '_id,f30d55e503b1d848b34ee57741b203d8052360dd873ea34802f3fa7a9ef34d0a\nhost.name,replacement3', + '_id,6f8cd5e8021dbb64598f2b7ec56bee21fd00d1e62d4e08905f86bf234873ee66\nhost.name,replacement3', + '_id,ce110da958fe0cf0c07599a21c68d90a64c93b7607aa27970a614c7f49598316\nhost.name,replacement3', + '_id,0866787b0027b4d908767ac16e35a1da00970c83632ba85be65f2ad371132b4f\nhost.name,replacement3', + '_id,b0fdf96721e361e1137d49a67e26d92f96b146392d7f44322bddc3d660abaef1\nhost.name,replacement3', + '_id,7b4f49f21cf141e67856d3207fb4ea069c8035b41f0ea501970694cf8bd43cbe\nhost.name,replacement3', + '_id,ea81d79104cbd442236b5bcdb7a3331de897aa4ce1523e622068038d048d0a9e\nhost.name,replacement3', + '_id,cdf3b5510bb5ed622e8cefd1ce6bedc52bdd99a4c1ead537af0603469e713c8b\nhost.name,replacement2', + '_id,6abe81eb6350fb08031761be029e7ab19f7e577a7c17a9c5ea1ed010ba1620e3\nhost.name,replacement2', + ]); + }); + + it('calls onNewReplacements for every alert', async () => { + const onNewReplacements = jest.fn(); + + await getAnonymizedAlerts({ + alertsIndexPattern, + anonymizationFields: mockAnonymizationFields, + esClient: mockEsClient, + onNewReplacements, + replacements: mockReplacements, + size, + }); + + expect(onNewReplacements).toHaveBeenCalledTimes(20); // 20 alerts in mockOpenAndAcknowledgedAlertsQueryResults + }); +}); diff --git a/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_anonymized_alerts.ts b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_anonymized_alerts.ts index 933a7ab55b924..5989caf439518 100644 --- a/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_anonymized_alerts.ts +++ b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_anonymized_alerts.ts @@ -28,7 +28,7 @@ export const getAnonymizedAlerts = async ({ onNewReplacements?: (replacements: Replacements) => void; replacements?: Replacements; size?: number; -}) => { +}): Promise<string[]> => { if (alertsIndexPattern == null || size == null || sizeIsOutOfRange(size)) { return []; } diff --git a/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_attack_discovery_prompt.test.ts b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_attack_discovery_prompt.test.ts new file mode 100644 index 0000000000000..bc290bf172382 --- /dev/null +++ b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_attack_discovery_prompt.test.ts @@ -0,0 +1,30 @@ +/* + * 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 { getAttackDiscoveryPrompt } from './get_attack_discovery_prompt'; + +describe('getAttackDiscoveryPrompt', () => { + it('should generate the correct attack discovery prompt', () => { + const anonymizedAlerts = ['Alert 1', 'Alert 2', 'Alert 3']; + + const expected = `You are a cyber security analyst tasked with analyzing security events from Elastic Security to identify and report on potential cyber attacks or progressions. Your report should focus on high-risk incidents that could severely impact the organization, rather than isolated alerts. Present your findings in a way that can be easily understood by anyone, regardless of their technical expertise, as if you were briefing the CISO. Break down your response into sections based on timing, hosts, and users involved. When correlating alerts, use kibana.alert.original_time when it's available, otherwise use @timestamp. Include appropriate context about the affected hosts and users. Describe how the attack progression might have occurred and, if feasible, attribute it to known threat groups. Prioritize high and critical alerts, but include lower-severity alerts if desired. In the description field, provide as much detail as possible, in a bulleted list explaining any attack progressions. Accuracy is of utmost importance. Escape backslashes to respect JSON validation. New lines must always be escaped with double backslashes, i.e. \\\\n to ensure valid JSON. Only return JSON output, as described above. Do not add any additional text to describe your output. + +Use context from the following open and acknowledged alerts to provide insights: + +""" +Alert 1 + +Alert 2 + +Alert 3 +""" +`; + + const prompt = getAttackDiscoveryPrompt({ anonymizedAlerts }); + + expect(prompt).toEqual(expected); + }); +}); diff --git a/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_output_parser.test.ts b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_output_parser.test.ts new file mode 100644 index 0000000000000..446611f87ea6a --- /dev/null +++ b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/get_output_parser.test.ts @@ -0,0 +1,31 @@ +/* + * 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 { getOutputParser } from './get_output_parser'; + +describe('getOutputParser', () => { + it('returns a structured output parser with the expected format instructions', () => { + const outputParser = getOutputParser(); + + const expected = `You must format your output as a JSON value that adheres to a given \"JSON Schema\" instance. + +\"JSON Schema\" is a declarative language that allows you to annotate and validate JSON documents. + +For example, the example \"JSON Schema\" instance {{\"properties\": {{\"foo\": {{\"description\": \"a list of test words\", \"type\": \"array\", \"items\": {{\"type\": \"string\"}}}}}}, \"required\": [\"foo\"]}}}} +would match an object with one required property, \"foo\". The \"type\" property specifies \"foo\" must be an \"array\", and the \"description\" property semantically describes it as \"a list of test words\". The items within \"foo\" must be strings. +Thus, the object {{\"foo\": [\"bar\", \"baz\"]}} is a well-formatted instance of this example \"JSON Schema\". The object {{\"properties\": {{\"foo\": [\"bar\", \"baz\"]}}}} is not well-formatted. + +Your output will be parsed and type-checked according to the provided schema instance, so make sure all fields in your output match the schema exactly and there are no trailing commas! + +Here is the JSON Schema instance your output must adhere to. Include the enclosing markdown codeblock: +\`\`\`json +{\"type\":\"array\",\"items\":{\"type\":\"object\",\"properties\":{\"alertIds\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"The alert IDs that the insight is based on.\"},\"detailsMarkdown\":{\"type\":\"string\",\"description\":\"A detailed insight with markdown that always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}\"},\"entitySummaryMarkdown\":{\"type\":\"string\",\"description\":\"A short (no more than a sentence) summary of the insight featuring only the host.name and user.name fields (when they are applicable), using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax\"},\"mitreAttackTactics\":{\"type\":\"array\",\"items\":{\"type\":\"string\"},\"description\":\"An array of MITRE ATT&CK tactic for the insight, using one of the following values: Reconnaissance,Initial Access,Execution,Persistence,Privilege Escalation,Discovery,Lateral Movement,Command and Control,Exfiltration\"},\"summaryMarkdown\":{\"type\":\"string\",\"description\":\"A markdown summary of insight, using the same {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax\"},\"title\":{\"type\":\"string\",\"description\":\"A short, no more than 7 words, title for the insight, NOT formatted with special syntax or markdown. This must be as brief as possible.\"}},\"required\":[\"alertIds\",\"detailsMarkdown\",\"summaryMarkdown\",\"title\"],\"additionalProperties\":false},\"description\":\"Insights with markdown that always uses special {{ field.name fieldValue1 fieldValue2 fieldValueN }} syntax for field names and values from the source data. Examples of CORRECT syntax (includes field names and values): {{ host.name hostNameValue }} {{ user.name userNameValue }} {{ source.ip sourceIpValue }} Examples of INCORRECT syntax (bad, because the field names are not included): {{ hostNameValue }} {{ userNameValue }} {{ sourceIpValue }}\",\"$schema\":\"http://json-schema.org/draft-07/schema#\"} +\`\`\` +`; + + expect(outputParser.getFormatInstructions()).toEqual(expected); + }); +}); diff --git a/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/helpers.ts b/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/helpers.ts deleted file mode 100644 index fd5d4cc668df8..0000000000000 --- a/x-pack/plugins/security_solution/server/assistant/tools/attack_discovery/helpers.ts +++ /dev/null @@ -1,21 +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 type { Replacements } from '@kbn/elastic-assistant-common'; - -export const getReplacementsRecords = ( - replacements: Array<{ value: string; uuid: string }> -): Replacements => - replacements.reduce<Record<string, string>>( - (acc, { value, uuid }) => ({ ...acc, [uuid]: value }), - {} - ); - -export const getReplacementsArray = ( - replacements: Replacements -): Array<{ value: string; uuid: string }> => - Object.entries(replacements).map(([uuid, value]) => ({ uuid, value })); From 97c57b6e5e0d581afa832a80f5925918b143ddf4 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 26 Jun 2024 15:05:55 +1000 Subject: [PATCH 19/22] [api-docs] 2024-06-26 Daily api_docs build (#186941) Generated by https://buildkite.com/elastic/kibana-api-docs-daily/builds/749 --- api_docs/actions.mdx | 2 +- api_docs/advanced_settings.mdx | 2 +- .../ai_assistant_management_selection.mdx | 2 +- api_docs/aiops.mdx | 2 +- api_docs/alerting.mdx | 4 +- api_docs/apm.mdx | 2 +- api_docs/apm_data_access.mdx | 2 +- api_docs/asset_manager.mdx | 2 +- api_docs/assets_data_access.mdx | 2 +- api_docs/banners.mdx | 2 +- api_docs/bfetch.mdx | 2 +- api_docs/canvas.mdx | 2 +- api_docs/cases.mdx | 2 +- api_docs/charts.mdx | 2 +- api_docs/cloud.mdx | 2 +- api_docs/cloud_data_migration.mdx | 2 +- api_docs/cloud_defend.mdx | 2 +- api_docs/cloud_experiments.mdx | 2 +- api_docs/cloud_security_posture.mdx | 2 +- api_docs/console.mdx | 2 +- api_docs/content_management.mdx | 2 +- api_docs/controls.mdx | 2 +- api_docs/custom_integrations.mdx | 2 +- api_docs/dashboard.mdx | 2 +- api_docs/dashboard_enhanced.mdx | 2 +- api_docs/data.mdx | 2 +- api_docs/data_quality.mdx | 2 +- api_docs/data_query.mdx | 2 +- api_docs/data_search.mdx | 2 +- api_docs/data_view_editor.mdx | 2 +- api_docs/data_view_field_editor.mdx | 2 +- api_docs/data_view_management.mdx | 2 +- api_docs/data_views.mdx | 2 +- api_docs/data_visualizer.mdx | 2 +- api_docs/dataset_quality.mdx | 2 +- api_docs/deprecations_by_api.mdx | 7 +- api_docs/deprecations_by_plugin.mdx | 4 +- api_docs/deprecations_by_team.mdx | 2 +- api_docs/dev_tools.mdx | 2 +- api_docs/discover.mdx | 2 +- api_docs/discover_enhanced.mdx | 2 +- api_docs/discover_shared.mdx | 2 +- api_docs/ecs_data_quality_dashboard.mdx | 2 +- api_docs/elastic_assistant.devdocs.json | 2 +- api_docs/elastic_assistant.mdx | 2 +- api_docs/embeddable.mdx | 2 +- api_docs/embeddable_enhanced.mdx | 2 +- api_docs/encrypted_saved_objects.mdx | 2 +- api_docs/enterprise_search.mdx | 2 +- api_docs/es_ui_shared.mdx | 2 +- api_docs/esql_data_grid.mdx | 2 +- api_docs/event_annotation.mdx | 2 +- api_docs/event_annotation_listing.mdx | 2 +- api_docs/event_log.devdocs.json | 6 +- api_docs/event_log.mdx | 2 +- api_docs/exploratory_view.mdx | 2 +- api_docs/expression_error.mdx | 2 +- api_docs/expression_gauge.mdx | 2 +- api_docs/expression_heatmap.mdx | 2 +- api_docs/expression_image.mdx | 2 +- api_docs/expression_legacy_metric_vis.mdx | 2 +- api_docs/expression_metric.mdx | 2 +- api_docs/expression_metric_vis.mdx | 2 +- api_docs/expression_partition_vis.mdx | 2 +- api_docs/expression_repeat_image.mdx | 2 +- api_docs/expression_reveal_image.mdx | 2 +- api_docs/expression_shape.mdx | 2 +- api_docs/expression_tagcloud.mdx | 2 +- api_docs/expression_x_y.mdx | 2 +- api_docs/expressions.mdx | 2 +- api_docs/features.mdx | 2 +- api_docs/field_formats.mdx | 2 +- api_docs/fields_metadata.mdx | 2 +- api_docs/file_upload.mdx | 2 +- api_docs/files.mdx | 2 +- api_docs/files_management.mdx | 2 +- api_docs/fleet.mdx | 2 +- api_docs/global_search.mdx | 2 +- api_docs/guided_onboarding.mdx | 2 +- api_docs/home.mdx | 2 +- api_docs/image_embeddable.mdx | 2 +- api_docs/index_lifecycle_management.mdx | 2 +- api_docs/index_management.mdx | 2 +- api_docs/infra.mdx | 2 +- api_docs/ingest_pipelines.mdx | 2 +- api_docs/inspector.mdx | 2 +- api_docs/integration_assistant.mdx | 2 +- api_docs/interactive_setup.mdx | 2 +- api_docs/investigate.mdx | 2 +- api_docs/kbn_ace.mdx | 2 +- api_docs/kbn_actions_types.mdx | 2 +- api_docs/kbn_aiops_components.mdx | 2 +- api_docs/kbn_aiops_log_pattern_analysis.mdx | 2 +- api_docs/kbn_aiops_log_rate_analysis.mdx | 2 +- .../kbn_alerting_api_integration_helpers.mdx | 2 +- api_docs/kbn_alerting_comparators.mdx | 2 +- api_docs/kbn_alerting_state_types.mdx | 2 +- api_docs/kbn_alerting_types.mdx | 2 +- api_docs/kbn_alerts_as_data_utils.mdx | 2 +- api_docs/kbn_alerts_ui_shared.mdx | 2 +- api_docs/kbn_analytics.mdx | 2 +- api_docs/kbn_analytics_collection_utils.mdx | 2 +- api_docs/kbn_apm_config_loader.mdx | 2 +- api_docs/kbn_apm_data_view.mdx | 2 +- api_docs/kbn_apm_synthtrace.mdx | 2 +- api_docs/kbn_apm_synthtrace_client.mdx | 2 +- api_docs/kbn_apm_utils.mdx | 2 +- api_docs/kbn_axe_config.mdx | 2 +- api_docs/kbn_bfetch_error.mdx | 2 +- api_docs/kbn_calculate_auto.mdx | 2 +- .../kbn_calculate_width_from_char_count.mdx | 2 +- api_docs/kbn_cases_components.mdx | 2 +- api_docs/kbn_cell_actions.mdx | 2 +- api_docs/kbn_chart_expressions_common.mdx | 2 +- api_docs/kbn_chart_icons.mdx | 2 +- api_docs/kbn_ci_stats_core.mdx | 2 +- api_docs/kbn_ci_stats_performance_metrics.mdx | 2 +- api_docs/kbn_ci_stats_reporter.mdx | 2 +- api_docs/kbn_cli_dev_mode.mdx | 2 +- api_docs/kbn_code_editor.mdx | 2 +- api_docs/kbn_code_editor_mock.mdx | 2 +- api_docs/kbn_code_owners.mdx | 2 +- api_docs/kbn_coloring.mdx | 2 +- api_docs/kbn_config.mdx | 2 +- api_docs/kbn_config_mocks.mdx | 2 +- api_docs/kbn_config_schema.mdx | 2 +- .../kbn_content_management_content_editor.mdx | 2 +- ...tent_management_tabbed_table_list_view.mdx | 2 +- ...kbn_content_management_table_list_view.mdx | 2 +- ...tent_management_table_list_view_common.mdx | 2 +- ...ntent_management_table_list_view_table.mdx | 2 +- .../kbn_content_management_user_profiles.mdx | 2 +- api_docs/kbn_content_management_utils.mdx | 2 +- .../kbn_core_analytics_browser.devdocs.json | 52 +- api_docs/kbn_core_analytics_browser.mdx | 2 +- .../kbn_core_analytics_browser_internal.mdx | 2 +- api_docs/kbn_core_analytics_browser_mocks.mdx | 2 +- .../kbn_core_analytics_server.devdocs.json | 52 +- api_docs/kbn_core_analytics_server.mdx | 2 +- .../kbn_core_analytics_server_internal.mdx | 2 +- api_docs/kbn_core_analytics_server_mocks.mdx | 2 +- api_docs/kbn_core_application_browser.mdx | 2 +- .../kbn_core_application_browser_internal.mdx | 2 +- .../kbn_core_application_browser_mocks.mdx | 2 +- api_docs/kbn_core_application_common.mdx | 2 +- api_docs/kbn_core_apps_browser_internal.mdx | 2 +- api_docs/kbn_core_apps_browser_mocks.mdx | 2 +- api_docs/kbn_core_apps_server_internal.mdx | 2 +- api_docs/kbn_core_base_browser_mocks.mdx | 2 +- api_docs/kbn_core_base_common.mdx | 2 +- api_docs/kbn_core_base_server_internal.mdx | 2 +- api_docs/kbn_core_base_server_mocks.mdx | 2 +- .../kbn_core_capabilities_browser_mocks.mdx | 2 +- api_docs/kbn_core_capabilities_common.mdx | 2 +- api_docs/kbn_core_capabilities_server.mdx | 2 +- .../kbn_core_capabilities_server_mocks.mdx | 2 +- api_docs/kbn_core_chrome_browser.mdx | 2 +- api_docs/kbn_core_chrome_browser_mocks.mdx | 2 +- api_docs/kbn_core_config_server_internal.mdx | 2 +- api_docs/kbn_core_custom_branding_browser.mdx | 2 +- ..._core_custom_branding_browser_internal.mdx | 2 +- ...kbn_core_custom_branding_browser_mocks.mdx | 2 +- api_docs/kbn_core_custom_branding_common.mdx | 2 +- api_docs/kbn_core_custom_branding_server.mdx | 2 +- ...n_core_custom_branding_server_internal.mdx | 2 +- .../kbn_core_custom_branding_server_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_browser.mdx | 2 +- ...kbn_core_deprecations_browser_internal.mdx | 2 +- .../kbn_core_deprecations_browser_mocks.mdx | 2 +- api_docs/kbn_core_deprecations_common.mdx | 2 +- api_docs/kbn_core_deprecations_server.mdx | 2 +- .../kbn_core_deprecations_server_internal.mdx | 2 +- .../kbn_core_deprecations_server_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_browser.mdx | 2 +- api_docs/kbn_core_doc_links_browser_mocks.mdx | 2 +- api_docs/kbn_core_doc_links_server.mdx | 2 +- api_docs/kbn_core_doc_links_server_mocks.mdx | 2 +- ...e_elasticsearch_client_server_internal.mdx | 2 +- ...core_elasticsearch_client_server_mocks.mdx | 2 +- api_docs/kbn_core_elasticsearch_server.mdx | 2 +- ...kbn_core_elasticsearch_server_internal.mdx | 2 +- .../kbn_core_elasticsearch_server_mocks.mdx | 2 +- .../kbn_core_environment_server_internal.mdx | 2 +- .../kbn_core_environment_server_mocks.mdx | 2 +- .../kbn_core_execution_context_browser.mdx | 2 +- ...ore_execution_context_browser_internal.mdx | 2 +- ...n_core_execution_context_browser_mocks.mdx | 2 +- .../kbn_core_execution_context_common.mdx | 2 +- .../kbn_core_execution_context_server.mdx | 2 +- ...core_execution_context_server_internal.mdx | 2 +- ...bn_core_execution_context_server_mocks.mdx | 2 +- api_docs/kbn_core_fatal_errors_browser.mdx | 2 +- .../kbn_core_fatal_errors_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_browser.mdx | 2 +- api_docs/kbn_core_http_browser_internal.mdx | 2 +- api_docs/kbn_core_http_browser_mocks.mdx | 2 +- api_docs/kbn_core_http_common.mdx | 2 +- .../kbn_core_http_context_server_mocks.mdx | 2 +- ...re_http_request_handler_context_server.mdx | 2 +- api_docs/kbn_core_http_resources_server.mdx | 2 +- ...bn_core_http_resources_server_internal.mdx | 2 +- .../kbn_core_http_resources_server_mocks.mdx | 2 +- .../kbn_core_http_router_server_internal.mdx | 2 +- .../kbn_core_http_router_server_mocks.mdx | 2 +- api_docs/kbn_core_http_server.devdocs.json | 8 + api_docs/kbn_core_http_server.mdx | 2 +- api_docs/kbn_core_http_server_internal.mdx | 2 +- api_docs/kbn_core_http_server_mocks.mdx | 2 +- api_docs/kbn_core_i18n_browser.mdx | 2 +- api_docs/kbn_core_i18n_browser_mocks.mdx | 2 +- api_docs/kbn_core_i18n_server.mdx | 2 +- api_docs/kbn_core_i18n_server_internal.mdx | 2 +- api_docs/kbn_core_i18n_server_mocks.mdx | 2 +- ...n_core_injected_metadata_browser_mocks.mdx | 2 +- ...kbn_core_integrations_browser_internal.mdx | 2 +- .../kbn_core_integrations_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_browser.mdx | 2 +- api_docs/kbn_core_lifecycle_browser_mocks.mdx | 2 +- api_docs/kbn_core_lifecycle_server.mdx | 2 +- api_docs/kbn_core_lifecycle_server_mocks.mdx | 2 +- api_docs/kbn_core_logging_browser_mocks.mdx | 2 +- api_docs/kbn_core_logging_common_internal.mdx | 2 +- api_docs/kbn_core_logging_server.mdx | 2 +- api_docs/kbn_core_logging_server_internal.mdx | 2 +- api_docs/kbn_core_logging_server_mocks.mdx | 2 +- ...ore_metrics_collectors_server_internal.mdx | 2 +- ...n_core_metrics_collectors_server_mocks.mdx | 2 +- api_docs/kbn_core_metrics_server.mdx | 2 +- api_docs/kbn_core_metrics_server_internal.mdx | 2 +- api_docs/kbn_core_metrics_server_mocks.mdx | 2 +- api_docs/kbn_core_mount_utils_browser.mdx | 2 +- api_docs/kbn_core_node_server.mdx | 2 +- api_docs/kbn_core_node_server_internal.mdx | 2 +- api_docs/kbn_core_node_server_mocks.mdx | 2 +- api_docs/kbn_core_notifications_browser.mdx | 2 +- ...bn_core_notifications_browser_internal.mdx | 2 +- .../kbn_core_notifications_browser_mocks.mdx | 2 +- api_docs/kbn_core_overlays_browser.mdx | 2 +- .../kbn_core_overlays_browser_internal.mdx | 2 +- api_docs/kbn_core_overlays_browser_mocks.mdx | 2 +- api_docs/kbn_core_plugins_browser.mdx | 2 +- api_docs/kbn_core_plugins_browser_mocks.mdx | 2 +- .../kbn_core_plugins_contracts_browser.mdx | 2 +- .../kbn_core_plugins_contracts_server.mdx | 2 +- api_docs/kbn_core_plugins_server.mdx | 2 +- api_docs/kbn_core_plugins_server_mocks.mdx | 2 +- api_docs/kbn_core_preboot_server.mdx | 2 +- api_docs/kbn_core_preboot_server_mocks.mdx | 2 +- api_docs/kbn_core_rendering_browser_mocks.mdx | 2 +- .../kbn_core_rendering_server_internal.mdx | 2 +- api_docs/kbn_core_rendering_server_mocks.mdx | 2 +- api_docs/kbn_core_root_server_internal.mdx | 2 +- .../kbn_core_saved_objects_api_browser.mdx | 2 +- .../kbn_core_saved_objects_api_server.mdx | 2 +- ...bn_core_saved_objects_api_server_mocks.mdx | 2 +- ...ore_saved_objects_base_server_internal.mdx | 2 +- ...n_core_saved_objects_base_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_browser.mdx | 2 +- ...bn_core_saved_objects_browser_internal.mdx | 2 +- .../kbn_core_saved_objects_browser_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_common.mdx | 2 +- ..._objects_import_export_server_internal.mdx | 2 +- ...ved_objects_import_export_server_mocks.mdx | 2 +- ...aved_objects_migration_server_internal.mdx | 2 +- ...e_saved_objects_migration_server_mocks.mdx | 2 +- api_docs/kbn_core_saved_objects_server.mdx | 2 +- ...kbn_core_saved_objects_server_internal.mdx | 2 +- .../kbn_core_saved_objects_server_mocks.mdx | 2 +- .../kbn_core_saved_objects_utils_server.mdx | 2 +- api_docs/kbn_core_security_browser.mdx | 2 +- .../kbn_core_security_browser_internal.mdx | 2 +- api_docs/kbn_core_security_browser_mocks.mdx | 2 +- api_docs/kbn_core_security_common.mdx | 2 +- api_docs/kbn_core_security_server.mdx | 2 +- .../kbn_core_security_server_internal.mdx | 2 +- api_docs/kbn_core_security_server_mocks.mdx | 2 +- api_docs/kbn_core_status_common.mdx | 2 +- api_docs/kbn_core_status_common_internal.mdx | 2 +- api_docs/kbn_core_status_server.mdx | 2 +- api_docs/kbn_core_status_server_internal.mdx | 2 +- api_docs/kbn_core_status_server_mocks.mdx | 2 +- ...core_test_helpers_deprecations_getters.mdx | 2 +- ...n_core_test_helpers_http_setup_browser.mdx | 2 +- api_docs/kbn_core_test_helpers_kbn_server.mdx | 2 +- .../kbn_core_test_helpers_model_versions.mdx | 2 +- ...n_core_test_helpers_so_type_serializer.mdx | 2 +- api_docs/kbn_core_test_helpers_test_utils.mdx | 2 +- api_docs/kbn_core_theme_browser.mdx | 2 +- api_docs/kbn_core_theme_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_browser.mdx | 2 +- .../kbn_core_ui_settings_browser_internal.mdx | 2 +- .../kbn_core_ui_settings_browser_mocks.mdx | 2 +- api_docs/kbn_core_ui_settings_common.mdx | 2 +- api_docs/kbn_core_ui_settings_server.mdx | 2 +- .../kbn_core_ui_settings_server_internal.mdx | 2 +- .../kbn_core_ui_settings_server_mocks.mdx | 2 +- api_docs/kbn_core_usage_data_server.mdx | 2 +- .../kbn_core_usage_data_server_internal.mdx | 2 +- api_docs/kbn_core_usage_data_server_mocks.mdx | 2 +- api_docs/kbn_core_user_profile_browser.mdx | 2 +- ...kbn_core_user_profile_browser_internal.mdx | 2 +- .../kbn_core_user_profile_browser_mocks.mdx | 2 +- api_docs/kbn_core_user_profile_common.mdx | 2 +- api_docs/kbn_core_user_profile_server.mdx | 2 +- .../kbn_core_user_profile_server_internal.mdx | 2 +- .../kbn_core_user_profile_server_mocks.mdx | 2 +- api_docs/kbn_core_user_settings_server.mdx | 2 +- .../kbn_core_user_settings_server_mocks.mdx | 2 +- api_docs/kbn_crypto.mdx | 2 +- api_docs/kbn_crypto_browser.mdx | 2 +- api_docs/kbn_custom_icons.mdx | 2 +- api_docs/kbn_custom_integrations.mdx | 2 +- api_docs/kbn_cypress_config.mdx | 2 +- api_docs/kbn_data_forge.mdx | 2 +- api_docs/kbn_data_service.mdx | 2 +- api_docs/kbn_data_stream_adapter.mdx | 2 +- api_docs/kbn_data_view_utils.mdx | 2 +- api_docs/kbn_datemath.mdx | 2 +- api_docs/kbn_deeplinks_analytics.mdx | 2 +- api_docs/kbn_deeplinks_devtools.mdx | 2 +- api_docs/kbn_deeplinks_fleet.mdx | 2 +- api_docs/kbn_deeplinks_management.mdx | 2 +- api_docs/kbn_deeplinks_ml.mdx | 2 +- api_docs/kbn_deeplinks_observability.mdx | 2 +- api_docs/kbn_deeplinks_search.mdx | 2 +- api_docs/kbn_deeplinks_security.mdx | 2 +- api_docs/kbn_deeplinks_shared.mdx | 2 +- api_docs/kbn_default_nav_analytics.mdx | 2 +- api_docs/kbn_default_nav_devtools.mdx | 2 +- api_docs/kbn_default_nav_management.mdx | 2 +- api_docs/kbn_default_nav_ml.mdx | 2 +- api_docs/kbn_dev_cli_errors.mdx | 2 +- api_docs/kbn_dev_cli_runner.mdx | 2 +- api_docs/kbn_dev_proc_runner.mdx | 2 +- api_docs/kbn_dev_utils.mdx | 2 +- api_docs/kbn_discover_utils.mdx | 2 +- api_docs/kbn_doc_links.mdx | 2 +- api_docs/kbn_docs_utils.mdx | 2 +- api_docs/kbn_dom_drag_drop.mdx | 2 +- api_docs/kbn_ebt.devdocs.json | 52 +- api_docs/kbn_ebt.mdx | 2 +- api_docs/kbn_ebt_tools.mdx | 2 +- api_docs/kbn_ecs_data_quality_dashboard.mdx | 2 +- api_docs/kbn_elastic_agent_utils.mdx | 2 +- api_docs/kbn_elastic_assistant.mdx | 2 +- .../kbn_elastic_assistant_common.devdocs.json | 384 ++++- api_docs/kbn_elastic_assistant_common.mdx | 4 +- api_docs/kbn_entities_schema.mdx | 2 +- api_docs/kbn_es.mdx | 2 +- api_docs/kbn_es_archiver.mdx | 2 +- api_docs/kbn_es_errors.mdx | 2 +- api_docs/kbn_es_query.mdx | 2 +- api_docs/kbn_es_types.mdx | 2 +- api_docs/kbn_eslint_plugin_imports.mdx | 2 +- api_docs/kbn_esql_ast.mdx | 2 +- api_docs/kbn_esql_utils.mdx | 2 +- api_docs/kbn_esql_validation_autocomplete.mdx | 2 +- api_docs/kbn_event_annotation_common.mdx | 2 +- api_docs/kbn_event_annotation_components.mdx | 2 +- api_docs/kbn_expandable_flyout.mdx | 2 +- api_docs/kbn_field_types.mdx | 2 +- api_docs/kbn_field_utils.mdx | 2 +- api_docs/kbn_find_used_node_modules.mdx | 2 +- api_docs/kbn_formatters.mdx | 2 +- .../kbn_ftr_common_functional_services.mdx | 2 +- .../kbn_ftr_common_functional_ui_services.mdx | 2 +- api_docs/kbn_generate.mdx | 2 +- api_docs/kbn_generate_console_definitions.mdx | 2 +- api_docs/kbn_generate_csv.mdx | 2 +- api_docs/kbn_grouping.mdx | 2 +- api_docs/kbn_guided_onboarding.mdx | 2 +- api_docs/kbn_handlebars.mdx | 2 +- api_docs/kbn_hapi_mocks.mdx | 2 +- api_docs/kbn_health_gateway_server.mdx | 2 +- api_docs/kbn_home_sample_data_card.mdx | 2 +- api_docs/kbn_home_sample_data_tab.mdx | 2 +- api_docs/kbn_i18n.mdx | 2 +- api_docs/kbn_i18n_react.mdx | 2 +- api_docs/kbn_import_resolver.mdx | 2 +- api_docs/kbn_index_management.mdx | 2 +- api_docs/kbn_inference_integration_flyout.mdx | 2 +- api_docs/kbn_infra_forge.mdx | 2 +- api_docs/kbn_interpreter.mdx | 2 +- api_docs/kbn_io_ts_utils.mdx | 2 +- api_docs/kbn_ipynb.mdx | 2 +- api_docs/kbn_jest_serializers.mdx | 2 +- api_docs/kbn_journeys.mdx | 2 +- api_docs/kbn_json_ast.mdx | 2 +- api_docs/kbn_json_schemas.mdx | 2 +- api_docs/kbn_kibana_manifest_schema.mdx | 2 +- .../kbn_language_documentation_popover.mdx | 2 +- api_docs/kbn_lens_embeddable_utils.mdx | 2 +- api_docs/kbn_lens_formula_docs.mdx | 2 +- api_docs/kbn_logging.mdx | 2 +- api_docs/kbn_logging_mocks.mdx | 2 +- api_docs/kbn_managed_content_badge.mdx | 2 +- api_docs/kbn_managed_vscode_config.mdx | 2 +- api_docs/kbn_management_cards_navigation.mdx | 2 +- .../kbn_management_settings_application.mdx | 2 +- ...ent_settings_components_field_category.mdx | 2 +- ...gement_settings_components_field_input.mdx | 2 +- ...nagement_settings_components_field_row.mdx | 2 +- ...bn_management_settings_components_form.mdx | 2 +- ...n_management_settings_field_definition.mdx | 2 +- api_docs/kbn_management_settings_ids.mdx | 2 +- ...n_management_settings_section_registry.mdx | 2 +- api_docs/kbn_management_settings_types.mdx | 2 +- .../kbn_management_settings_utilities.mdx | 2 +- api_docs/kbn_management_storybook_config.mdx | 2 +- api_docs/kbn_mapbox_gl.mdx | 2 +- api_docs/kbn_maps_vector_tile_utils.mdx | 2 +- api_docs/kbn_ml_agg_utils.mdx | 2 +- api_docs/kbn_ml_anomaly_utils.mdx | 2 +- api_docs/kbn_ml_cancellable_search.mdx | 2 +- api_docs/kbn_ml_category_validator.mdx | 2 +- api_docs/kbn_ml_chi2test.mdx | 2 +- .../kbn_ml_data_frame_analytics_utils.mdx | 2 +- api_docs/kbn_ml_data_grid.mdx | 2 +- api_docs/kbn_ml_date_picker.mdx | 2 +- api_docs/kbn_ml_date_utils.mdx | 2 +- api_docs/kbn_ml_error_utils.mdx | 2 +- api_docs/kbn_ml_in_memory_table.mdx | 2 +- api_docs/kbn_ml_is_defined.mdx | 2 +- api_docs/kbn_ml_is_populated_object.mdx | 2 +- api_docs/kbn_ml_kibana_theme.mdx | 2 +- api_docs/kbn_ml_local_storage.mdx | 2 +- api_docs/kbn_ml_nested_property.mdx | 2 +- api_docs/kbn_ml_number_utils.mdx | 2 +- api_docs/kbn_ml_query_utils.mdx | 2 +- api_docs/kbn_ml_random_sampler_utils.mdx | 2 +- api_docs/kbn_ml_route_utils.mdx | 2 +- api_docs/kbn_ml_runtime_field_utils.mdx | 2 +- api_docs/kbn_ml_string_hash.mdx | 2 +- api_docs/kbn_ml_time_buckets.mdx | 2 +- api_docs/kbn_ml_trained_models_utils.mdx | 2 +- api_docs/kbn_ml_ui_actions.mdx | 2 +- api_docs/kbn_ml_url_state.mdx | 2 +- api_docs/kbn_mock_idp_utils.mdx | 2 +- api_docs/kbn_monaco.mdx | 2 +- api_docs/kbn_object_versioning.mdx | 2 +- api_docs/kbn_observability_alert_details.mdx | 2 +- .../kbn_observability_alerting_test_data.mdx | 2 +- ...ility_get_padded_alert_time_range_util.mdx | 2 +- api_docs/kbn_openapi_bundler.mdx | 2 +- api_docs/kbn_openapi_generator.mdx | 2 +- api_docs/kbn_optimizer.mdx | 2 +- api_docs/kbn_optimizer_webpack_helpers.mdx | 2 +- api_docs/kbn_osquery_io_ts_types.mdx | 2 +- api_docs/kbn_panel_loader.mdx | 2 +- ..._performance_testing_dataset_extractor.mdx | 2 +- api_docs/kbn_plugin_check.mdx | 2 +- api_docs/kbn_plugin_generator.mdx | 2 +- api_docs/kbn_plugin_helpers.mdx | 2 +- api_docs/kbn_presentation_containers.mdx | 2 +- api_docs/kbn_presentation_publishing.mdx | 2 +- api_docs/kbn_profiling_utils.mdx | 2 +- api_docs/kbn_random_sampling.mdx | 2 +- api_docs/kbn_react_field.mdx | 2 +- api_docs/kbn_react_hooks.mdx | 2 +- api_docs/kbn_react_kibana_context_common.mdx | 2 +- api_docs/kbn_react_kibana_context_render.mdx | 2 +- api_docs/kbn_react_kibana_context_root.mdx | 2 +- api_docs/kbn_react_kibana_context_styled.mdx | 2 +- api_docs/kbn_react_kibana_context_theme.mdx | 2 +- api_docs/kbn_react_kibana_mount.mdx | 2 +- api_docs/kbn_repo_file_maps.mdx | 2 +- api_docs/kbn_repo_linter.mdx | 2 +- api_docs/kbn_repo_path.mdx | 2 +- api_docs/kbn_repo_source_classifier.mdx | 2 +- api_docs/kbn_reporting_common.mdx | 2 +- api_docs/kbn_reporting_csv_share_panel.mdx | 2 +- api_docs/kbn_reporting_export_types_csv.mdx | 2 +- .../kbn_reporting_export_types_csv_common.mdx | 2 +- api_docs/kbn_reporting_export_types_pdf.mdx | 2 +- .../kbn_reporting_export_types_pdf_common.mdx | 2 +- api_docs/kbn_reporting_export_types_png.mdx | 2 +- .../kbn_reporting_export_types_png_common.mdx | 2 +- api_docs/kbn_reporting_mocks_server.mdx | 2 +- api_docs/kbn_reporting_public.mdx | 2 +- api_docs/kbn_reporting_server.mdx | 2 +- api_docs/kbn_resizable_layout.mdx | 2 +- .../kbn_response_ops_feature_flag_service.mdx | 2 +- api_docs/kbn_rison.mdx | 2 +- api_docs/kbn_rollup.mdx | 2 +- api_docs/kbn_router_to_openapispec.mdx | 2 +- api_docs/kbn_router_utils.mdx | 2 +- api_docs/kbn_rrule.mdx | 2 +- api_docs/kbn_rule_data_utils.mdx | 2 +- api_docs/kbn_saved_objects_settings.mdx | 2 +- api_docs/kbn_search_api_panels.mdx | 2 +- api_docs/kbn_search_connectors.mdx | 2 +- api_docs/kbn_search_errors.mdx | 2 +- api_docs/kbn_search_index_documents.mdx | 2 +- api_docs/kbn_search_response_warnings.mdx | 2 +- api_docs/kbn_search_types.mdx | 2 +- ...n_security_api_key_management.devdocs.json | 1259 +++++++++++++++++ api_docs/kbn_security_api_key_management.mdx | 39 + .../kbn_security_form_components.devdocs.json | 727 ++++++++++ api_docs/kbn_security_form_components.mdx | 36 + api_docs/kbn_security_hardening.mdx | 2 +- ..._security_plugin_types_common.devdocs.json | 510 +++++++ api_docs/kbn_security_plugin_types_common.mdx | 4 +- ..._security_plugin_types_public.devdocs.json | 12 - api_docs/kbn_security_plugin_types_public.mdx | 2 +- ..._security_plugin_types_server.devdocs.json | 340 +++++ api_docs/kbn_security_plugin_types_server.mdx | 4 +- api_docs/kbn_security_solution_features.mdx | 2 +- api_docs/kbn_security_solution_navigation.mdx | 2 +- api_docs/kbn_security_solution_side_nav.mdx | 2 +- ...kbn_security_solution_storybook_config.mdx | 2 +- .../kbn_securitysolution_autocomplete.mdx | 2 +- api_docs/kbn_securitysolution_data_table.mdx | 2 +- api_docs/kbn_securitysolution_ecs.mdx | 2 +- api_docs/kbn_securitysolution_es_utils.mdx | 2 +- ...ritysolution_exception_list_components.mdx | 2 +- api_docs/kbn_securitysolution_hook_utils.mdx | 2 +- ..._securitysolution_io_ts_alerting_types.mdx | 2 +- .../kbn_securitysolution_io_ts_list_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_types.mdx | 2 +- api_docs/kbn_securitysolution_io_ts_utils.mdx | 2 +- api_docs/kbn_securitysolution_list_api.mdx | 2 +- .../kbn_securitysolution_list_constants.mdx | 2 +- api_docs/kbn_securitysolution_list_hooks.mdx | 2 +- api_docs/kbn_securitysolution_list_utils.mdx | 2 +- api_docs/kbn_securitysolution_rules.mdx | 2 +- api_docs/kbn_securitysolution_t_grid.mdx | 2 +- api_docs/kbn_securitysolution_utils.mdx | 2 +- api_docs/kbn_server_http_tools.mdx | 2 +- api_docs/kbn_server_route_repository.mdx | 2 +- api_docs/kbn_serverless_common_settings.mdx | 2 +- .../kbn_serverless_observability_settings.mdx | 2 +- api_docs/kbn_serverless_project_switcher.mdx | 2 +- api_docs/kbn_serverless_search_settings.mdx | 2 +- api_docs/kbn_serverless_security_settings.mdx | 2 +- api_docs/kbn_serverless_storybook_config.mdx | 2 +- api_docs/kbn_shared_svg.mdx | 2 +- api_docs/kbn_shared_ux_avatar_solution.mdx | 2 +- .../kbn_shared_ux_button_exit_full_screen.mdx | 2 +- api_docs/kbn_shared_ux_button_toolbar.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data.mdx | 2 +- api_docs/kbn_shared_ux_card_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_chrome_navigation.mdx | 2 +- api_docs/kbn_shared_ux_error_boundary.mdx | 2 +- api_docs/kbn_shared_ux_file_context.mdx | 2 +- api_docs/kbn_shared_ux_file_image.mdx | 2 +- api_docs/kbn_shared_ux_file_image_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_mocks.mdx | 2 +- api_docs/kbn_shared_ux_file_picker.mdx | 2 +- api_docs/kbn_shared_ux_file_types.mdx | 2 +- api_docs/kbn_shared_ux_file_upload.mdx | 2 +- api_docs/kbn_shared_ux_file_util.mdx | 2 +- api_docs/kbn_shared_ux_link_redirect_app.mdx | 2 +- .../kbn_shared_ux_link_redirect_app_mocks.mdx | 2 +- api_docs/kbn_shared_ux_markdown.mdx | 2 +- api_docs/kbn_shared_ux_markdown_mocks.mdx | 2 +- .../kbn_shared_ux_page_analytics_no_data.mdx | 2 +- ...shared_ux_page_analytics_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_no_data.mdx | 2 +- ...bn_shared_ux_page_kibana_no_data_mocks.mdx | 2 +- .../kbn_shared_ux_page_kibana_template.mdx | 2 +- ...n_shared_ux_page_kibana_template_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data.mdx | 2 +- .../kbn_shared_ux_page_no_data_config.mdx | 2 +- ...bn_shared_ux_page_no_data_config_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_no_data_mocks.mdx | 2 +- api_docs/kbn_shared_ux_page_solution_nav.mdx | 2 +- .../kbn_shared_ux_prompt_no_data_views.mdx | 2 +- ...n_shared_ux_prompt_no_data_views_mocks.mdx | 2 +- api_docs/kbn_shared_ux_prompt_not_found.mdx | 2 +- api_docs/kbn_shared_ux_router.mdx | 2 +- api_docs/kbn_shared_ux_router_mocks.mdx | 2 +- api_docs/kbn_shared_ux_storybook_config.mdx | 2 +- api_docs/kbn_shared_ux_storybook_mock.mdx | 2 +- api_docs/kbn_shared_ux_tabbed_modal.mdx | 2 +- api_docs/kbn_shared_ux_utility.mdx | 2 +- api_docs/kbn_slo_schema.mdx | 2 +- api_docs/kbn_some_dev_log.mdx | 2 +- api_docs/kbn_sort_predicates.mdx | 2 +- api_docs/kbn_std.mdx | 2 +- api_docs/kbn_stdio_dev_helpers.mdx | 2 +- api_docs/kbn_storybook.mdx | 2 +- api_docs/kbn_telemetry_tools.mdx | 2 +- api_docs/kbn_test.mdx | 2 +- api_docs/kbn_test_eui_helpers.mdx | 2 +- api_docs/kbn_test_jest_helpers.mdx | 2 +- api_docs/kbn_test_subj_selector.mdx | 2 +- api_docs/kbn_text_based_editor.mdx | 2 +- api_docs/kbn_timerange.mdx | 2 +- api_docs/kbn_tooling_log.mdx | 2 +- api_docs/kbn_triggers_actions_ui_types.mdx | 2 +- api_docs/kbn_try_in_console.mdx | 2 +- api_docs/kbn_ts_projects.mdx | 2 +- api_docs/kbn_typed_react_router_config.mdx | 2 +- api_docs/kbn_ui_actions_browser.mdx | 2 +- api_docs/kbn_ui_shared_deps_src.mdx | 2 +- api_docs/kbn_ui_theme.mdx | 2 +- api_docs/kbn_unified_data_table.mdx | 2 +- api_docs/kbn_unified_doc_viewer.mdx | 2 +- api_docs/kbn_unified_field_list.mdx | 2 +- api_docs/kbn_unsaved_changes_badge.mdx | 2 +- api_docs/kbn_unsaved_changes_prompt.mdx | 2 +- api_docs/kbn_use_tracked_promise.mdx | 2 +- api_docs/kbn_user_profile_components.mdx | 2 +- api_docs/kbn_utility_types.mdx | 2 +- api_docs/kbn_utility_types_jest.mdx | 2 +- api_docs/kbn_utils.mdx | 2 +- api_docs/kbn_visualization_ui_components.mdx | 2 +- api_docs/kbn_visualization_utils.mdx | 2 +- api_docs/kbn_xstate_utils.mdx | 2 +- api_docs/kbn_yarn_lock_validator.mdx | 2 +- api_docs/kbn_zod_helpers.mdx | 2 +- api_docs/kibana_overview.mdx | 2 +- api_docs/kibana_react.mdx | 2 +- api_docs/kibana_utils.mdx | 2 +- api_docs/kubernetes_security.mdx | 2 +- api_docs/lens.mdx | 2 +- api_docs/license_api_guard.mdx | 2 +- api_docs/license_management.mdx | 2 +- api_docs/licensing.mdx | 2 +- api_docs/links.mdx | 2 +- api_docs/lists.mdx | 2 +- api_docs/logs_data_access.mdx | 2 +- api_docs/logs_explorer.mdx | 2 +- api_docs/logs_shared.mdx | 2 +- api_docs/management.mdx | 2 +- api_docs/maps.mdx | 2 +- api_docs/maps_ems.mdx | 2 +- api_docs/metrics_data_access.mdx | 2 +- api_docs/ml.mdx | 2 +- api_docs/mock_idp_plugin.mdx | 2 +- api_docs/monitoring.mdx | 2 +- api_docs/monitoring_collection.mdx | 2 +- api_docs/navigation.mdx | 2 +- api_docs/newsfeed.mdx | 2 +- api_docs/no_data_page.mdx | 2 +- api_docs/notifications.mdx | 2 +- api_docs/observability.devdocs.json | 305 +--- api_docs/observability.mdx | 7 +- api_docs/observability_a_i_assistant.mdx | 2 +- api_docs/observability_a_i_assistant_app.mdx | 2 +- .../observability_ai_assistant_management.mdx | 2 +- api_docs/observability_logs_explorer.mdx | 2 +- api_docs/observability_onboarding.mdx | 2 +- api_docs/observability_shared.mdx | 2 +- api_docs/osquery.mdx | 2 +- api_docs/painless_lab.mdx | 2 +- api_docs/plugin_directory.mdx | 20 +- api_docs/presentation_panel.mdx | 2 +- api_docs/presentation_util.mdx | 2 +- api_docs/profiling.mdx | 2 +- api_docs/profiling_data_access.mdx | 2 +- api_docs/remote_clusters.mdx | 2 +- api_docs/reporting.mdx | 2 +- api_docs/rollup.mdx | 2 +- api_docs/rule_registry.mdx | 2 +- api_docs/runtime_fields.mdx | 2 +- api_docs/saved_objects.mdx | 2 +- api_docs/saved_objects_finder.mdx | 2 +- api_docs/saved_objects_management.mdx | 2 +- api_docs/saved_objects_tagging.mdx | 2 +- api_docs/saved_objects_tagging_oss.mdx | 2 +- api_docs/saved_search.mdx | 2 +- api_docs/screenshot_mode.mdx | 2 +- api_docs/screenshotting.mdx | 2 +- api_docs/search_connectors.mdx | 2 +- api_docs/search_homepage.mdx | 2 +- api_docs/search_inference_endpoints.mdx | 2 +- api_docs/search_notebooks.mdx | 2 +- api_docs/search_playground.mdx | 2 +- api_docs/security.devdocs.json | 77 +- api_docs/security.mdx | 4 +- api_docs/security_solution.mdx | 2 +- api_docs/security_solution_ess.mdx | 2 +- api_docs/security_solution_serverless.mdx | 2 +- api_docs/serverless.mdx | 2 +- api_docs/serverless_observability.mdx | 2 +- api_docs/serverless_search.mdx | 2 +- api_docs/session_view.mdx | 2 +- api_docs/share.mdx | 2 +- api_docs/slo.mdx | 2 +- api_docs/snapshot_restore.mdx | 2 +- api_docs/spaces.mdx | 2 +- api_docs/stack_alerts.mdx | 2 +- api_docs/stack_connectors.mdx | 2 +- api_docs/task_manager.mdx | 2 +- api_docs/telemetry.mdx | 2 +- api_docs/telemetry_collection_manager.mdx | 2 +- api_docs/telemetry_collection_xpack.mdx | 2 +- api_docs/telemetry_management_section.mdx | 2 +- api_docs/text_based_languages.mdx | 2 +- api_docs/threat_intelligence.mdx | 2 +- api_docs/timelines.mdx | 2 +- api_docs/transform.mdx | 2 +- api_docs/triggers_actions_ui.mdx | 2 +- api_docs/ui_actions.mdx | 2 +- api_docs/ui_actions_enhanced.mdx | 2 +- api_docs/unified_doc_viewer.mdx | 2 +- api_docs/unified_histogram.mdx | 2 +- api_docs/unified_search.mdx | 2 +- api_docs/unified_search_autocomplete.mdx | 2 +- api_docs/uptime.mdx | 2 +- api_docs/url_forwarding.mdx | 2 +- api_docs/usage_collection.mdx | 2 +- api_docs/ux.mdx | 2 +- api_docs/vis_default_editor.mdx | 2 +- api_docs/vis_type_gauge.mdx | 2 +- api_docs/vis_type_heatmap.mdx | 2 +- api_docs/vis_type_pie.mdx | 2 +- api_docs/vis_type_table.mdx | 2 +- api_docs/vis_type_timelion.mdx | 2 +- api_docs/vis_type_timeseries.mdx | 2 +- api_docs/vis_type_vega.mdx | 2 +- api_docs/vis_type_vislib.mdx | 2 +- api_docs/vis_type_xy.mdx | 2 +- api_docs/visualizations.mdx | 2 +- 715 files changed, 4216 insertions(+), 1083 deletions(-) create mode 100644 api_docs/kbn_security_api_key_management.devdocs.json create mode 100644 api_docs/kbn_security_api_key_management.mdx create mode 100644 api_docs/kbn_security_form_components.devdocs.json create mode 100644 api_docs/kbn_security_form_components.mdx diff --git a/api_docs/actions.mdx b/api_docs/actions.mdx index 09effcc15af47..3ef2b2c496a05 100644 --- a/api_docs/actions.mdx +++ b/api_docs/actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/actions title: "actions" image: https://source.unsplash.com/400x175/?github description: API docs for the actions plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'actions'] --- import actionsObj from './actions.devdocs.json'; diff --git a/api_docs/advanced_settings.mdx b/api_docs/advanced_settings.mdx index 48b12cc676e37..62d47283f9ab1 100644 --- a/api_docs/advanced_settings.mdx +++ b/api_docs/advanced_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/advancedSettings title: "advancedSettings" image: https://source.unsplash.com/400x175/?github description: API docs for the advancedSettings plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'advancedSettings'] --- import advancedSettingsObj from './advanced_settings.devdocs.json'; diff --git a/api_docs/ai_assistant_management_selection.mdx b/api_docs/ai_assistant_management_selection.mdx index f605d5d9e57a4..dba116e3caa06 100644 --- a/api_docs/ai_assistant_management_selection.mdx +++ b/api_docs/ai_assistant_management_selection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiAssistantManagementSelection title: "aiAssistantManagementSelection" image: https://source.unsplash.com/400x175/?github description: API docs for the aiAssistantManagementSelection plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiAssistantManagementSelection'] --- import aiAssistantManagementSelectionObj from './ai_assistant_management_selection.devdocs.json'; diff --git a/api_docs/aiops.mdx b/api_docs/aiops.mdx index 20975c87cb9f2..31060eb64d799 100644 --- a/api_docs/aiops.mdx +++ b/api_docs/aiops.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/aiops title: "aiops" image: https://source.unsplash.com/400x175/?github description: API docs for the aiops plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'aiops'] --- import aiopsObj from './aiops.devdocs.json'; diff --git a/api_docs/alerting.mdx b/api_docs/alerting.mdx index 0ec3086f3f527..a93f6b38c2c5f 100644 --- a/api_docs/alerting.mdx +++ b/api_docs/alerting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/alerting title: "alerting" image: https://source.unsplash.com/400x175/?github description: API docs for the alerting plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'alerting'] --- import alertingObj from './alerting.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-o | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 868 | 1 | 836 | 54 | +| 868 | 1 | 836 | 52 | ## Client diff --git a/api_docs/apm.mdx b/api_docs/apm.mdx index ff183ce581e53..80985ba0dc051 100644 --- a/api_docs/apm.mdx +++ b/api_docs/apm.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apm title: "apm" image: https://source.unsplash.com/400x175/?github description: API docs for the apm plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apm'] --- import apmObj from './apm.devdocs.json'; diff --git a/api_docs/apm_data_access.mdx b/api_docs/apm_data_access.mdx index dcdaecf32f2c7..468e11668d99e 100644 --- a/api_docs/apm_data_access.mdx +++ b/api_docs/apm_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/apmDataAccess title: "apmDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the apmDataAccess plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'apmDataAccess'] --- import apmDataAccessObj from './apm_data_access.devdocs.json'; diff --git a/api_docs/asset_manager.mdx b/api_docs/asset_manager.mdx index 69fd08bb29522..c0b8edc34d032 100644 --- a/api_docs/asset_manager.mdx +++ b/api_docs/asset_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetManager title: "assetManager" image: https://source.unsplash.com/400x175/?github description: API docs for the assetManager plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetManager'] --- import assetManagerObj from './asset_manager.devdocs.json'; diff --git a/api_docs/assets_data_access.mdx b/api_docs/assets_data_access.mdx index 6dbb347ac11de..19b4157343964 100644 --- a/api_docs/assets_data_access.mdx +++ b/api_docs/assets_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/assetsDataAccess title: "assetsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the assetsDataAccess plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'assetsDataAccess'] --- import assetsDataAccessObj from './assets_data_access.devdocs.json'; diff --git a/api_docs/banners.mdx b/api_docs/banners.mdx index 738294d2c30c5..209c7695ca893 100644 --- a/api_docs/banners.mdx +++ b/api_docs/banners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/banners title: "banners" image: https://source.unsplash.com/400x175/?github description: API docs for the banners plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'banners'] --- import bannersObj from './banners.devdocs.json'; diff --git a/api_docs/bfetch.mdx b/api_docs/bfetch.mdx index dd8917ee7a9b5..c0be563d174e3 100644 --- a/api_docs/bfetch.mdx +++ b/api_docs/bfetch.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/bfetch title: "bfetch" image: https://source.unsplash.com/400x175/?github description: API docs for the bfetch plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'bfetch'] --- import bfetchObj from './bfetch.devdocs.json'; diff --git a/api_docs/canvas.mdx b/api_docs/canvas.mdx index c5be47417d2f7..f77526228d134 100644 --- a/api_docs/canvas.mdx +++ b/api_docs/canvas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/canvas title: "canvas" image: https://source.unsplash.com/400x175/?github description: API docs for the canvas plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'canvas'] --- import canvasObj from './canvas.devdocs.json'; diff --git a/api_docs/cases.mdx b/api_docs/cases.mdx index 724038e9c7a21..f2bcceb644b68 100644 --- a/api_docs/cases.mdx +++ b/api_docs/cases.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cases title: "cases" image: https://source.unsplash.com/400x175/?github description: API docs for the cases plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cases'] --- import casesObj from './cases.devdocs.json'; diff --git a/api_docs/charts.mdx b/api_docs/charts.mdx index beafd08efa8ba..79cbe0081b402 100644 --- a/api_docs/charts.mdx +++ b/api_docs/charts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/charts title: "charts" image: https://source.unsplash.com/400x175/?github description: API docs for the charts plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'charts'] --- import chartsObj from './charts.devdocs.json'; diff --git a/api_docs/cloud.mdx b/api_docs/cloud.mdx index ad1714a4df84e..64638ed59922a 100644 --- a/api_docs/cloud.mdx +++ b/api_docs/cloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloud title: "cloud" image: https://source.unsplash.com/400x175/?github description: API docs for the cloud plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloud'] --- import cloudObj from './cloud.devdocs.json'; diff --git a/api_docs/cloud_data_migration.mdx b/api_docs/cloud_data_migration.mdx index c7c82da516b1d..86a4e03e2145f 100644 --- a/api_docs/cloud_data_migration.mdx +++ b/api_docs/cloud_data_migration.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDataMigration title: "cloudDataMigration" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDataMigration plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDataMigration'] --- import cloudDataMigrationObj from './cloud_data_migration.devdocs.json'; diff --git a/api_docs/cloud_defend.mdx b/api_docs/cloud_defend.mdx index 3ae901b64378e..0bcd8635d0b15 100644 --- a/api_docs/cloud_defend.mdx +++ b/api_docs/cloud_defend.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudDefend title: "cloudDefend" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudDefend plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudDefend'] --- import cloudDefendObj from './cloud_defend.devdocs.json'; diff --git a/api_docs/cloud_experiments.mdx b/api_docs/cloud_experiments.mdx index be4dd137fb094..7fdc7e7c2c81d 100644 --- a/api_docs/cloud_experiments.mdx +++ b/api_docs/cloud_experiments.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudExperiments title: "cloudExperiments" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudExperiments plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudExperiments'] --- import cloudExperimentsObj from './cloud_experiments.devdocs.json'; diff --git a/api_docs/cloud_security_posture.mdx b/api_docs/cloud_security_posture.mdx index 01e9aff3e226f..4372f9bcb9599 100644 --- a/api_docs/cloud_security_posture.mdx +++ b/api_docs/cloud_security_posture.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/cloudSecurityPosture title: "cloudSecurityPosture" image: https://source.unsplash.com/400x175/?github description: API docs for the cloudSecurityPosture plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'cloudSecurityPosture'] --- import cloudSecurityPostureObj from './cloud_security_posture.devdocs.json'; diff --git a/api_docs/console.mdx b/api_docs/console.mdx index 6c67b8414c935..e46fa3d66c8c5 100644 --- a/api_docs/console.mdx +++ b/api_docs/console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/console title: "console" image: https://source.unsplash.com/400x175/?github description: API docs for the console plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'console'] --- import consoleObj from './console.devdocs.json'; diff --git a/api_docs/content_management.mdx b/api_docs/content_management.mdx index beaa579ae1344..ef76d532876ff 100644 --- a/api_docs/content_management.mdx +++ b/api_docs/content_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/contentManagement title: "contentManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the contentManagement plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'contentManagement'] --- import contentManagementObj from './content_management.devdocs.json'; diff --git a/api_docs/controls.mdx b/api_docs/controls.mdx index 8d4f10f17d3a0..2f432ddb602e2 100644 --- a/api_docs/controls.mdx +++ b/api_docs/controls.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/controls title: "controls" image: https://source.unsplash.com/400x175/?github description: API docs for the controls plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'controls'] --- import controlsObj from './controls.devdocs.json'; diff --git a/api_docs/custom_integrations.mdx b/api_docs/custom_integrations.mdx index fad021c4ef14d..bf0601e2ae19a 100644 --- a/api_docs/custom_integrations.mdx +++ b/api_docs/custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/customIntegrations title: "customIntegrations" image: https://source.unsplash.com/400x175/?github description: API docs for the customIntegrations plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'customIntegrations'] --- import customIntegrationsObj from './custom_integrations.devdocs.json'; diff --git a/api_docs/dashboard.mdx b/api_docs/dashboard.mdx index adc7ea958c63d..f09873b00f6fe 100644 --- a/api_docs/dashboard.mdx +++ b/api_docs/dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboard title: "dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboard plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboard'] --- import dashboardObj from './dashboard.devdocs.json'; diff --git a/api_docs/dashboard_enhanced.mdx b/api_docs/dashboard_enhanced.mdx index 8e63d3a47eccb..19f044031fd34 100644 --- a/api_docs/dashboard_enhanced.mdx +++ b/api_docs/dashboard_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dashboardEnhanced title: "dashboardEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the dashboardEnhanced plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dashboardEnhanced'] --- import dashboardEnhancedObj from './dashboard_enhanced.devdocs.json'; diff --git a/api_docs/data.mdx b/api_docs/data.mdx index 3a92ada15257a..deed8dbdaaa6a 100644 --- a/api_docs/data.mdx +++ b/api_docs/data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data title: "data" image: https://source.unsplash.com/400x175/?github description: API docs for the data plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data'] --- import dataObj from './data.devdocs.json'; diff --git a/api_docs/data_quality.mdx b/api_docs/data_quality.mdx index 33e5dc706f470..525b7e1ac6a42 100644 --- a/api_docs/data_quality.mdx +++ b/api_docs/data_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataQuality title: "dataQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the dataQuality plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataQuality'] --- import dataQualityObj from './data_quality.devdocs.json'; diff --git a/api_docs/data_query.mdx b/api_docs/data_query.mdx index c50fe3222ed9b..20286f2260754 100644 --- a/api_docs/data_query.mdx +++ b/api_docs/data_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-query title: "data.query" image: https://source.unsplash.com/400x175/?github description: API docs for the data.query plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.query'] --- import dataQueryObj from './data_query.devdocs.json'; diff --git a/api_docs/data_search.mdx b/api_docs/data_search.mdx index e05f16328e36e..89a6d3496bbaa 100644 --- a/api_docs/data_search.mdx +++ b/api_docs/data_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/data-search title: "data.search" image: https://source.unsplash.com/400x175/?github description: API docs for the data.search plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'data.search'] --- import dataSearchObj from './data_search.devdocs.json'; diff --git a/api_docs/data_view_editor.mdx b/api_docs/data_view_editor.mdx index 1bac0c37fc642..faffcf8fff74d 100644 --- a/api_docs/data_view_editor.mdx +++ b/api_docs/data_view_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewEditor title: "dataViewEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewEditor plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewEditor'] --- import dataViewEditorObj from './data_view_editor.devdocs.json'; diff --git a/api_docs/data_view_field_editor.mdx b/api_docs/data_view_field_editor.mdx index a2fc2abe24162..7dfc13ecbd9df 100644 --- a/api_docs/data_view_field_editor.mdx +++ b/api_docs/data_view_field_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewFieldEditor title: "dataViewFieldEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewFieldEditor plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewFieldEditor'] --- import dataViewFieldEditorObj from './data_view_field_editor.devdocs.json'; diff --git a/api_docs/data_view_management.mdx b/api_docs/data_view_management.mdx index c6ca168d93386..2120e2a767d7d 100644 --- a/api_docs/data_view_management.mdx +++ b/api_docs/data_view_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViewManagement title: "dataViewManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViewManagement plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViewManagement'] --- import dataViewManagementObj from './data_view_management.devdocs.json'; diff --git a/api_docs/data_views.mdx b/api_docs/data_views.mdx index 9a6c35d7ada99..c2e2adab9a422 100644 --- a/api_docs/data_views.mdx +++ b/api_docs/data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataViews title: "dataViews" image: https://source.unsplash.com/400x175/?github description: API docs for the dataViews plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataViews'] --- import dataViewsObj from './data_views.devdocs.json'; diff --git a/api_docs/data_visualizer.mdx b/api_docs/data_visualizer.mdx index da378dbbbf881..b034b5a027e1d 100644 --- a/api_docs/data_visualizer.mdx +++ b/api_docs/data_visualizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/dataVisualizer title: "dataVisualizer" image: https://source.unsplash.com/400x175/?github description: API docs for the dataVisualizer plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'dataVisualizer'] --- import dataVisualizerObj from './data_visualizer.devdocs.json'; diff --git a/api_docs/dataset_quality.mdx b/api_docs/dataset_quality.mdx index 69f42503ddbdd..2fe52912d71c3 100644 --- a/api_docs/dataset_quality.mdx +++ b/api_docs/dataset_quality.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/datasetQuality title: "datasetQuality" image: https://source.unsplash.com/400x175/?github description: API docs for the datasetQuality plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'datasetQuality'] --- import datasetQualityObj from './dataset_quality.devdocs.json'; diff --git a/api_docs/deprecations_by_api.mdx b/api_docs/deprecations_by_api.mdx index 718d37eb4a914..165846fd25365 100644 --- a/api_docs/deprecations_by_api.mdx +++ b/api_docs/deprecations_by_api.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByApi slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-api title: Deprecated API usage by API description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -50,7 +50,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibTimelinesPluginApi" section="def-common.IndexFieldsStrategyResponse" text="IndexFieldsStrategyResponse"/> | securitySolution | - | | <DocLink id="kibKbnCoreSavedObjectsCommonPluginApi" section="def-common.SavedObject" text="SavedObject"/> | @kbn/core-saved-objects-api-browser, @kbn/core-saved-objects-browser-internal, @kbn/core-saved-objects-api-server, @kbn/core, home, savedObjectsTagging, canvas, savedObjects, @kbn/core-saved-objects-browser-mocks, @kbn/core-saved-objects-import-export-server-internal, savedObjectsTaggingOss, lists, securitySolution, upgradeAssistant, savedObjectsManagement, @kbn/core-ui-settings-server-internal | - | | <DocLink id="kibKbnCoreSavedObjectsServerPluginApi" section="def-common.SavedObjectsType.convertToMultiNamespaceTypeVersion" text="convertToMultiNamespaceTypeVersion"/> | @kbn/core-saved-objects-migration-server-internal, actions, dataViews, data, alerting, lens, cases, savedSearch, canvas, savedObjectsTagging, graph, lists, maps, visualizations, securitySolution, dashboard, @kbn/core-test-helpers-so-type-serializer | - | -| <DocLink id="kibKbnSecurityPluginTypesPublicPluginApi" section="def-public.SecurityPluginStart.authc" text="authc"/> | dataViews, security, maps, imageEmbeddable, securitySolution, serverlessSearch, cloudLinks, observabilityAIAssistantApp, cases, apm | - | +| <DocLink id="kibKbnSecurityPluginTypesPublicPluginApi" section="def-public.SecurityPluginStart.authc" text="authc"/> | dataViews, security, imageEmbeddable, securitySolution, serverlessSearch, cloudLinks, observabilityAIAssistantApp, cases, apm | - | | <DocLink id="kibKbnSecurityPluginTypesPublicPluginApi" section="def-public.SecurityPluginStart.userProfiles" text="userProfiles"/> | security, cases, searchPlayground, securitySolution | - | | <DocLink id="kibKbnSecuritysolutionListConstantsPluginApi" section="def-common.ENDPOINT_TRUSTED_APPS_LIST_ID" text="ENDPOINT_TRUSTED_APPS_LIST_ID"/> | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | | <DocLink id="kibKbnSecuritysolutionListConstantsPluginApi" section="def-common.ENDPOINT_TRUSTED_APPS_LIST_NAME" text="ENDPOINT_TRUSTED_APPS_LIST_NAME"/> | lists, securitySolution, @kbn/securitysolution-io-ts-list-types | - | @@ -118,7 +118,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnPresentationPublishingPluginApi" section="def-common.apiHasLegacyLibraryTransforms" text="apiHasLegacyLibraryTransforms"/> | dashboard | - | | <DocLink id="kibKbnPresentationPublishingPluginApi" section="def-common.HasLegacyLibraryTransforms" text="HasLegacyLibraryTransforms"/> | embeddable, dashboard | - | | <DocLink id="kibKbnPresentationPublishingPluginApi" section="def-common.HasLibraryTransforms" text="HasLibraryTransforms"/> | dashboard, maps | - | -| <DocLink id="kibSecurityPluginApi" section="def-public.SecurityPluginSetup.authc" text="authc"/> | dataVisualizer, security | - | | <DocLink id="kibDataPluginApi" section="def-common.DataView.flattenHit" text="flattenHit"/> | dataViews, maps | - | | <DocLink id="kibDataPluginApi" section="def-common.DataView.removeScriptedField" text="removeScriptedField"/> | dataViews, dataViewManagement | - | | <DocLink id="kibDataPluginApi" section="def-common.DataView.getScriptedFields" text="getScriptedFields"/> | dataViews, dataViewManagement | - | @@ -151,6 +150,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibExpressionPartitionVisPluginApi" section="def-common.LabelsParams.truncate" text="truncate"/> | visTypePie | - | | <DocLink id="kibExpressionPartitionVisPluginApi" section="def-common.LabelsParams.last_level" text="last_level"/> | visTypePie | - | | <DocLink id="kibKbnCoreLoggingServerPluginApi" section="def-common.NumericRollingStrategyConfig.max" text="max"/> | @kbn/core-logging-server-internal, security | - | +| <DocLink id="kibKbnSecurityPluginTypesPublicPluginApi" section="def-public.SecurityPluginSetup.authc" text="authc"/> | security | - | | <DocLink id="kibKibanaReactPluginApi" section="def-public.toMountPoint" text="toMountPoint"/> | observabilityShared | - | | <DocLink id="kibKibanaReactPluginApi" section="def-common.KibanaStyledComponentsThemeProviderDecorator" text="KibanaStyledComponentsThemeProviderDecorator"/> | @kbn/react-kibana-context-styled, kibanaReact | - | | <DocLink id="kibKbnCoreSavedObjectsServerPluginApi" section="def-common.SavedObjectMigrationContext.convertToMultiNamespaceTypeVersion" text="convertToMultiNamespaceTypeVersion"/> | encryptedSavedObjects | - | @@ -232,6 +232,7 @@ Safe to remove. | <DocLink id="kibListsPluginApi" section="def-server.ListClient.setListPolicy" text="setListPolicy"/> | lists | | <DocLink id="kibListsPluginApi" section="def-server.ListClient.setListItemPolicy" text="setListItemPolicy"/> | lists | | <DocLink id="kibSavedObjectsPluginApi" section="def-public.SavedObjectsStart.SavedObjectClass" text="SavedObjectClass"/> | savedObjects | +| <DocLink id="kibSecurityPluginApi" section="def-public.SecurityPluginSetup.authc" text="authc"/> | security | | <DocLink id="kibServerlessPluginApi" section="def-public.ServerlessPluginStart.setSideNavComponentDeprecated" text="setSideNavComponentDeprecated"/> | serverless | | <DocLink id="kibTaskManagerPluginApi" section="def-server.ConcreteTaskInstance.interval" text="interval"/> | taskManager | | <DocLink id="kibTaskManagerPluginApi" section="def-server.ConcreteTaskInstance.numSkippedRuns" text="numSkippedRuns"/> | taskManager | diff --git a/api_docs/deprecations_by_plugin.mdx b/api_docs/deprecations_by_plugin.mdx index 611c05d483811..6a9c021aa0aad 100644 --- a/api_docs/deprecations_by_plugin.mdx +++ b/api_docs/deprecations_by_plugin.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsByPlugin slug: /kibana-dev-docs/api-meta/deprecated-api-list-by-plugin title: Deprecated API usage by plugin description: A list of deprecated APIs, which plugins are still referencing them, and when they need to be removed by. -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -713,7 +713,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | ---------------|-----------|-----------| | <DocLink id="kibDataPluginApi" section="def-public.DataPublicPluginStart.fieldFormats" text="fieldFormats"/> | [document_stats.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_row/document_stats.tsx#:~:text=fieldFormats), [distinct_values.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_row/distinct_values.tsx#:~:text=fieldFormats), [top_values.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/top_values/top_values.tsx#:~:text=fieldFormats), [choropleth_map.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/stats_table/components/field_data_expanded_row/choropleth_map.tsx#:~:text=fieldFormats), [default_value_formatter.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/data_drift/charts/default_value_formatter.ts#:~:text=fieldFormats) | - | | <DocLink id="kibDataViewsPluginApi" section="def-common.AbstractDataView.title" text="title"/> | [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=title) | - | -| <DocLink id="kibSecurityPluginApi" section="def-public.SecurityPluginSetup.authc" text="authc"/> | [filebeat_config_flyout.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx#:~:text=authc), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=authc), [filebeat_config_flyout.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx#:~:text=authc), [use_data_visualizer_grid_data.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts#:~:text=authc) | - | | <DocLink id="kibKbnCoreLifecycleBrowserPluginApi" section="def-common.CoreStart.savedObjects" text="savedObjects"/> | [index_data_visualizer.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/public/application/index_data_visualizer/index_data_visualizer.tsx#:~:text=savedObjects) | - | | <DocLink id="kibKbnCoreSavedObjectsApiBrowserPluginApi" section="def-common.SimpleSavedObject" text="SimpleSavedObject"/> | [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/common/types/index.ts#:~:text=SimpleSavedObject), [index.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/data_visualizer/common/types/index.ts#:~:text=SimpleSavedObject) | - | @@ -1078,7 +1077,6 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnCoreSavedObjectsServerPluginApi" section="def-common.SavedObjectsType.migrations" text="migrations"/> | [setup_saved_objects.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts#:~:text=migrations) | - | | <DocLink id="kibKbnCoreSavedObjectsServerPluginApi" section="def-common.SavedObjectsType.convertToMultiNamespaceTypeVersion" text="convertToMultiNamespaceTypeVersion"/> | [setup_saved_objects.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/server/saved_objects/setup_saved_objects.ts#:~:text=convertToMultiNamespaceTypeVersion) | - | | <DocLink id="kibKbnPresentationPublishingPluginApi" section="def-common.HasLibraryTransforms" text="HasLibraryTransforms"/> | [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/react_embeddable/types.ts#:~:text=HasLibraryTransforms), [types.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/react_embeddable/types.ts#:~:text=HasLibraryTransforms), [library_transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/react_embeddable/library_transforms.ts#:~:text=HasLibraryTransforms), [library_transforms.ts](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/react_embeddable/library_transforms.ts#:~:text=HasLibraryTransforms) | - | -| <DocLink id="kibKbnSecurityPluginTypesPublicPluginApi" section="def-public.SecurityPluginStart.authc" text="authc"/> | [es_search_source.tsx](https://github.com/elastic/kibana/tree/main/x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx#:~:text=authc) | - | diff --git a/api_docs/deprecations_by_team.mdx b/api_docs/deprecations_by_team.mdx index 0bfc05484d357..e877b7cdd5c8d 100644 --- a/api_docs/deprecations_by_team.mdx +++ b/api_docs/deprecations_by_team.mdx @@ -7,7 +7,7 @@ id: kibDevDocsDeprecationsDueByTeam slug: /kibana-dev-docs/api-meta/deprecations-due-by-team title: Deprecated APIs due to be removed, by team description: Lists the teams that are referencing deprecated APIs with a remove by date. -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- diff --git a/api_docs/dev_tools.mdx b/api_docs/dev_tools.mdx index a8b40ae0098bc..28b657f608f0a 100644 --- a/api_docs/dev_tools.mdx +++ b/api_docs/dev_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/devTools title: "devTools" image: https://source.unsplash.com/400x175/?github description: API docs for the devTools plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'devTools'] --- import devToolsObj from './dev_tools.devdocs.json'; diff --git a/api_docs/discover.mdx b/api_docs/discover.mdx index 10c2f66afeef5..d27dcb0c6139f 100644 --- a/api_docs/discover.mdx +++ b/api_docs/discover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discover title: "discover" image: https://source.unsplash.com/400x175/?github description: API docs for the discover plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discover'] --- import discoverObj from './discover.devdocs.json'; diff --git a/api_docs/discover_enhanced.mdx b/api_docs/discover_enhanced.mdx index 3fd6c6649a60e..2a44324508a68 100644 --- a/api_docs/discover_enhanced.mdx +++ b/api_docs/discover_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverEnhanced title: "discoverEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverEnhanced plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverEnhanced'] --- import discoverEnhancedObj from './discover_enhanced.devdocs.json'; diff --git a/api_docs/discover_shared.mdx b/api_docs/discover_shared.mdx index 2640f05cc8fbb..36b405044c23e 100644 --- a/api_docs/discover_shared.mdx +++ b/api_docs/discover_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/discoverShared title: "discoverShared" image: https://source.unsplash.com/400x175/?github description: API docs for the discoverShared plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'discoverShared'] --- import discoverSharedObj from './discover_shared.devdocs.json'; diff --git a/api_docs/ecs_data_quality_dashboard.mdx b/api_docs/ecs_data_quality_dashboard.mdx index b7a3e2d32f549..025cc7cffe416 100644 --- a/api_docs/ecs_data_quality_dashboard.mdx +++ b/api_docs/ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ecsDataQualityDashboard title: "ecsDataQualityDashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the ecsDataQualityDashboard plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ecsDataQualityDashboard'] --- import ecsDataQualityDashboardObj from './ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/elastic_assistant.devdocs.json b/api_docs/elastic_assistant.devdocs.json index e543e43a16801..595bd103d2f58 100644 --- a/api_docs/elastic_assistant.devdocs.json +++ b/api_docs/elastic_assistant.devdocs.json @@ -1609,7 +1609,7 @@ "section": "def-common.KibanaRequest", "text": "KibanaRequest" }, - "<unknown, unknown, { actionTypeId: string; subAction: \"invokeAI\" | \"invokeStream\"; replacements: {} & { [k: string]: string; }; conversationId?: string | undefined; message?: string | undefined; model?: string | undefined; alertsIndexPattern?: string | undefined; allow?: string[] | undefined; allowReplacement?: string[] | undefined; isEnabledKnowledgeBase?: boolean | undefined; isEnabledRAGAlerts?: boolean | undefined; size?: number | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; } | { connectorId: string; actionTypeId: string; size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; }, any>" + "<unknown, unknown, { actionTypeId: string; subAction: \"invokeAI\" | \"invokeStream\"; replacements: {} & { [k: string]: string; }; conversationId?: string | undefined; message?: string | undefined; model?: string | undefined; alertsIndexPattern?: string | undefined; allow?: string[] | undefined; allowReplacement?: string[] | undefined; isEnabledKnowledgeBase?: boolean | undefined; isEnabledRAGAlerts?: boolean | undefined; size?: number | undefined; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; } | { size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; }, any>" ], "path": "x-pack/plugins/elastic_assistant/server/types.ts", "deprecated": false, diff --git a/api_docs/elastic_assistant.mdx b/api_docs/elastic_assistant.mdx index a27396eceb10f..0fb7c1937c495 100644 --- a/api_docs/elastic_assistant.mdx +++ b/api_docs/elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/elasticAssistant title: "elasticAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the elasticAssistant plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'elasticAssistant'] --- import elasticAssistantObj from './elastic_assistant.devdocs.json'; diff --git a/api_docs/embeddable.mdx b/api_docs/embeddable.mdx index 4a1e1892ac1f2..3c424595ae96c 100644 --- a/api_docs/embeddable.mdx +++ b/api_docs/embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddable title: "embeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddable plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddable'] --- import embeddableObj from './embeddable.devdocs.json'; diff --git a/api_docs/embeddable_enhanced.mdx b/api_docs/embeddable_enhanced.mdx index 800f74a30629e..651a1579787e7 100644 --- a/api_docs/embeddable_enhanced.mdx +++ b/api_docs/embeddable_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/embeddableEnhanced title: "embeddableEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the embeddableEnhanced plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'embeddableEnhanced'] --- import embeddableEnhancedObj from './embeddable_enhanced.devdocs.json'; diff --git a/api_docs/encrypted_saved_objects.mdx b/api_docs/encrypted_saved_objects.mdx index 325761a3d9299..4e8f583f003ec 100644 --- a/api_docs/encrypted_saved_objects.mdx +++ b/api_docs/encrypted_saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/encryptedSavedObjects title: "encryptedSavedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the encryptedSavedObjects plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'encryptedSavedObjects'] --- import encryptedSavedObjectsObj from './encrypted_saved_objects.devdocs.json'; diff --git a/api_docs/enterprise_search.mdx b/api_docs/enterprise_search.mdx index a98d68f483e1e..7df2979fd0bc2 100644 --- a/api_docs/enterprise_search.mdx +++ b/api_docs/enterprise_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/enterpriseSearch title: "enterpriseSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the enterpriseSearch plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'enterpriseSearch'] --- import enterpriseSearchObj from './enterprise_search.devdocs.json'; diff --git a/api_docs/es_ui_shared.mdx b/api_docs/es_ui_shared.mdx index 044157fb69d1a..5120eb114e92d 100644 --- a/api_docs/es_ui_shared.mdx +++ b/api_docs/es_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esUiShared title: "esUiShared" image: https://source.unsplash.com/400x175/?github description: API docs for the esUiShared plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esUiShared'] --- import esUiSharedObj from './es_ui_shared.devdocs.json'; diff --git a/api_docs/esql_data_grid.mdx b/api_docs/esql_data_grid.mdx index 56d8ec14e06f7..2139d70dfc720 100644 --- a/api_docs/esql_data_grid.mdx +++ b/api_docs/esql_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/esqlDataGrid title: "esqlDataGrid" image: https://source.unsplash.com/400x175/?github description: API docs for the esqlDataGrid plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'esqlDataGrid'] --- import esqlDataGridObj from './esql_data_grid.devdocs.json'; diff --git a/api_docs/event_annotation.mdx b/api_docs/event_annotation.mdx index ed65e311f907e..0c426207a66f6 100644 --- a/api_docs/event_annotation.mdx +++ b/api_docs/event_annotation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotation title: "eventAnnotation" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotation plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotation'] --- import eventAnnotationObj from './event_annotation.devdocs.json'; diff --git a/api_docs/event_annotation_listing.mdx b/api_docs/event_annotation_listing.mdx index 7b5b2548279c0..6e43569ae6c21 100644 --- a/api_docs/event_annotation_listing.mdx +++ b/api_docs/event_annotation_listing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventAnnotationListing title: "eventAnnotationListing" image: https://source.unsplash.com/400x175/?github description: API docs for the eventAnnotationListing plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventAnnotationListing'] --- import eventAnnotationListingObj from './event_annotation_listing.devdocs.json'; diff --git a/api_docs/event_log.devdocs.json b/api_docs/event_log.devdocs.json index 76c10e0330333..5ffc692e82fb7 100644 --- a/api_docs/event_log.devdocs.json +++ b/api_docs/event_log.devdocs.json @@ -1450,7 +1450,7 @@ "label": "data", "description": [], "signature": [ - "(Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; license?: string | undefined; uuid?: string | undefined; category?: string | undefined; description?: string | undefined; version?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; uuid?: string | undefined; flapping?: boolean | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; severity?: string | number | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; code?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}> | undefined)[]" + "(Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; license?: string | undefined; uuid?: string | undefined; category?: string | undefined; description?: string | undefined; version?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; uuid?: string | undefined; flapping?: boolean | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; severity?: string | number | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; code?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}> | undefined)[]" ], "path": "x-pack/plugins/event_log/server/es/cluster_client_adapter.ts", "deprecated": false, @@ -1470,7 +1470,7 @@ "label": "IEvent", "description": [], "signature": [ - "DeepPartial<DeepWriteable<Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; license?: string | undefined; uuid?: string | undefined; category?: string | undefined; description?: string | undefined; version?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; uuid?: string | undefined; flapping?: boolean | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; severity?: string | number | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; code?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}>>> | undefined" + "DeepPartial<DeepWriteable<Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; license?: string | undefined; uuid?: string | undefined; category?: string | undefined; description?: string | undefined; version?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; uuid?: string | undefined; flapping?: boolean | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; severity?: string | number | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; code?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}>>> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, @@ -1485,7 +1485,7 @@ "label": "IValidatedEvent", "description": [], "signature": [ - "Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; license?: string | undefined; uuid?: string | undefined; category?: string | undefined; description?: string | undefined; version?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; uuid?: string | undefined; flapping?: boolean | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; severity?: string | number | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; code?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; provider?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}> | undefined" + "Readonly<{ log?: Readonly<{ logger?: string | undefined; level?: string | undefined; } & {}> | undefined; error?: Readonly<{ id?: string | undefined; type?: string | undefined; message?: string | undefined; code?: string | undefined; stack_trace?: string | undefined; } & {}> | undefined; '@timestamp'?: string | undefined; message?: string | undefined; tags?: string[] | undefined; rule?: Readonly<{ id?: string | undefined; name?: string | undefined; license?: string | undefined; uuid?: string | undefined; category?: string | undefined; description?: string | undefined; version?: string | undefined; reference?: string | undefined; author?: string[] | undefined; ruleset?: string | undefined; } & {}> | undefined; kibana?: Readonly<{ task?: Readonly<{ id?: string | undefined; schedule_delay?: string | number | undefined; scheduled?: string | undefined; } & {}> | undefined; action?: Readonly<{ id?: string | undefined; name?: string | undefined; execution?: Readonly<{ source?: string | undefined; uuid?: string | undefined; gen_ai?: Readonly<{ usage?: Readonly<{ prompt_tokens?: string | number | undefined; completion_tokens?: string | number | undefined; total_tokens?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; } & {}> | undefined; alerting?: Readonly<{ outcome?: string | undefined; status?: string | undefined; summary?: Readonly<{ recovered?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; new?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; ongoing?: Readonly<{ count?: string | number | undefined; } & {}> | undefined; } & {}> | undefined; instance_id?: string | undefined; action_group_id?: string | undefined; action_subgroup?: string | undefined; } & {}> | undefined; alert?: Readonly<{ rule?: Readonly<{ consumer?: string | undefined; revision?: string | number | undefined; execution?: Readonly<{ uuid?: string | undefined; status?: string | undefined; metrics?: Readonly<{ total_search_duration_ms?: string | number | undefined; total_indexing_duration_ms?: string | number | undefined; number_of_triggered_actions?: string | number | undefined; number_of_generated_actions?: string | number | undefined; alert_counts?: Readonly<{ recovered?: string | number | undefined; active?: string | number | undefined; new?: string | number | undefined; } & {}> | undefined; number_of_delayed_alerts?: string | number | undefined; number_of_searches?: string | number | undefined; es_search_duration_ms?: string | number | undefined; execution_gap_duration_s?: string | number | undefined; rule_type_run_duration_ms?: string | number | undefined; process_alerts_duration_ms?: string | number | undefined; trigger_actions_duration_ms?: string | number | undefined; process_rule_duration_ms?: string | number | undefined; claim_to_start_duration_ms?: string | number | undefined; persist_alerts_duration_ms?: string | number | undefined; prepare_rule_duration_ms?: string | number | undefined; total_run_duration_ms?: string | number | undefined; total_enrichment_duration_ms?: string | number | undefined; } & {}> | undefined; status_order?: string | number | undefined; backfill?: Readonly<{ id?: string | undefined; start?: string | undefined; interval?: string | undefined; } & {}> | undefined; } & {}> | undefined; rule_type_id?: string | undefined; } & {}> | undefined; uuid?: string | undefined; flapping?: boolean | undefined; maintenance_window_ids?: string[] | undefined; } & {}> | undefined; version?: string | undefined; server_uuid?: string | undefined; saved_objects?: Readonly<{ id?: string | undefined; type?: string | undefined; namespace?: string | undefined; rel?: string | undefined; type_id?: string | undefined; space_agnostic?: boolean | undefined; } & {}>[] | undefined; space_ids?: string[] | undefined; } & {}> | undefined; event?: Readonly<{ id?: string | undefined; type?: string[] | undefined; reason?: string | undefined; action?: string | undefined; start?: string | undefined; end?: string | undefined; outcome?: string | undefined; duration?: string | number | undefined; category?: string[] | undefined; timezone?: string | undefined; risk_score?: number | undefined; severity?: string | number | undefined; url?: string | undefined; created?: string | undefined; dataset?: string | undefined; code?: string | undefined; provider?: string | undefined; hash?: string | undefined; ingested?: string | undefined; kind?: string | undefined; module?: string | undefined; original?: string | undefined; reference?: string | undefined; risk_score_norm?: number | undefined; sequence?: string | number | undefined; } & {}> | undefined; ecs?: Readonly<{ version?: string | undefined; } & {}> | undefined; user?: Readonly<{ id?: string | undefined; name?: string | undefined; } & {}> | undefined; } & {}> | undefined" ], "path": "x-pack/plugins/event_log/generated/schemas.ts", "deprecated": false, diff --git a/api_docs/event_log.mdx b/api_docs/event_log.mdx index cf2c837e2df51..096325f1df979 100644 --- a/api_docs/event_log.mdx +++ b/api_docs/event_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/eventLog title: "eventLog" image: https://source.unsplash.com/400x175/?github description: API docs for the eventLog plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'eventLog'] --- import eventLogObj from './event_log.devdocs.json'; diff --git a/api_docs/exploratory_view.mdx b/api_docs/exploratory_view.mdx index 058ae8b436beb..86843f83c7398 100644 --- a/api_docs/exploratory_view.mdx +++ b/api_docs/exploratory_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/exploratoryView title: "exploratoryView" image: https://source.unsplash.com/400x175/?github description: API docs for the exploratoryView plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'exploratoryView'] --- import exploratoryViewObj from './exploratory_view.devdocs.json'; diff --git a/api_docs/expression_error.mdx b/api_docs/expression_error.mdx index b039d717055c2..7af6805150c9f 100644 --- a/api_docs/expression_error.mdx +++ b/api_docs/expression_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionError title: "expressionError" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionError plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionError'] --- import expressionErrorObj from './expression_error.devdocs.json'; diff --git a/api_docs/expression_gauge.mdx b/api_docs/expression_gauge.mdx index 194234ca12f5e..400b3977786b1 100644 --- a/api_docs/expression_gauge.mdx +++ b/api_docs/expression_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionGauge title: "expressionGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionGauge plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionGauge'] --- import expressionGaugeObj from './expression_gauge.devdocs.json'; diff --git a/api_docs/expression_heatmap.mdx b/api_docs/expression_heatmap.mdx index 186ac111cb751..cc4d834468359 100644 --- a/api_docs/expression_heatmap.mdx +++ b/api_docs/expression_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionHeatmap title: "expressionHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionHeatmap plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionHeatmap'] --- import expressionHeatmapObj from './expression_heatmap.devdocs.json'; diff --git a/api_docs/expression_image.mdx b/api_docs/expression_image.mdx index b279b857c9a7b..44ff5376821d7 100644 --- a/api_docs/expression_image.mdx +++ b/api_docs/expression_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionImage title: "expressionImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionImage plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionImage'] --- import expressionImageObj from './expression_image.devdocs.json'; diff --git a/api_docs/expression_legacy_metric_vis.mdx b/api_docs/expression_legacy_metric_vis.mdx index e91310eeaa622..795795580e440 100644 --- a/api_docs/expression_legacy_metric_vis.mdx +++ b/api_docs/expression_legacy_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionLegacyMetricVis title: "expressionLegacyMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionLegacyMetricVis plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionLegacyMetricVis'] --- import expressionLegacyMetricVisObj from './expression_legacy_metric_vis.devdocs.json'; diff --git a/api_docs/expression_metric.mdx b/api_docs/expression_metric.mdx index 5f548c1262f3c..43b3035131f31 100644 --- a/api_docs/expression_metric.mdx +++ b/api_docs/expression_metric.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetric title: "expressionMetric" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetric plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetric'] --- import expressionMetricObj from './expression_metric.devdocs.json'; diff --git a/api_docs/expression_metric_vis.mdx b/api_docs/expression_metric_vis.mdx index b5cdd1685781d..9e273411c9ddc 100644 --- a/api_docs/expression_metric_vis.mdx +++ b/api_docs/expression_metric_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionMetricVis title: "expressionMetricVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionMetricVis plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionMetricVis'] --- import expressionMetricVisObj from './expression_metric_vis.devdocs.json'; diff --git a/api_docs/expression_partition_vis.mdx b/api_docs/expression_partition_vis.mdx index 4e08f879dd534..0822896e61de6 100644 --- a/api_docs/expression_partition_vis.mdx +++ b/api_docs/expression_partition_vis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionPartitionVis title: "expressionPartitionVis" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionPartitionVis plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionPartitionVis'] --- import expressionPartitionVisObj from './expression_partition_vis.devdocs.json'; diff --git a/api_docs/expression_repeat_image.mdx b/api_docs/expression_repeat_image.mdx index 519cb3beabd68..1c719338ebcc8 100644 --- a/api_docs/expression_repeat_image.mdx +++ b/api_docs/expression_repeat_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRepeatImage title: "expressionRepeatImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRepeatImage plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRepeatImage'] --- import expressionRepeatImageObj from './expression_repeat_image.devdocs.json'; diff --git a/api_docs/expression_reveal_image.mdx b/api_docs/expression_reveal_image.mdx index 21e94f7aa02c9..16313ea72c09b 100644 --- a/api_docs/expression_reveal_image.mdx +++ b/api_docs/expression_reveal_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionRevealImage title: "expressionRevealImage" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionRevealImage plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionRevealImage'] --- import expressionRevealImageObj from './expression_reveal_image.devdocs.json'; diff --git a/api_docs/expression_shape.mdx b/api_docs/expression_shape.mdx index 815a3ea90e84d..3ea992543c042 100644 --- a/api_docs/expression_shape.mdx +++ b/api_docs/expression_shape.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionShape title: "expressionShape" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionShape plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionShape'] --- import expressionShapeObj from './expression_shape.devdocs.json'; diff --git a/api_docs/expression_tagcloud.mdx b/api_docs/expression_tagcloud.mdx index dd60c91a6bdb6..2cda4ca2b45cf 100644 --- a/api_docs/expression_tagcloud.mdx +++ b/api_docs/expression_tagcloud.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionTagcloud title: "expressionTagcloud" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionTagcloud plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionTagcloud'] --- import expressionTagcloudObj from './expression_tagcloud.devdocs.json'; diff --git a/api_docs/expression_x_y.mdx b/api_docs/expression_x_y.mdx index b86a9be6c6ba6..1f2bc205e49d0 100644 --- a/api_docs/expression_x_y.mdx +++ b/api_docs/expression_x_y.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressionXY title: "expressionXY" image: https://source.unsplash.com/400x175/?github description: API docs for the expressionXY plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressionXY'] --- import expressionXYObj from './expression_x_y.devdocs.json'; diff --git a/api_docs/expressions.mdx b/api_docs/expressions.mdx index 239c549026403..0c523ac8e2745 100644 --- a/api_docs/expressions.mdx +++ b/api_docs/expressions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/expressions title: "expressions" image: https://source.unsplash.com/400x175/?github description: API docs for the expressions plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'expressions'] --- import expressionsObj from './expressions.devdocs.json'; diff --git a/api_docs/features.mdx b/api_docs/features.mdx index b13a2e8a72d8d..ea62ae268aba7 100644 --- a/api_docs/features.mdx +++ b/api_docs/features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/features title: "features" image: https://source.unsplash.com/400x175/?github description: API docs for the features plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'features'] --- import featuresObj from './features.devdocs.json'; diff --git a/api_docs/field_formats.mdx b/api_docs/field_formats.mdx index 8505bc3ef0a3e..cefe41affc3a1 100644 --- a/api_docs/field_formats.mdx +++ b/api_docs/field_formats.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldFormats title: "fieldFormats" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldFormats plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldFormats'] --- import fieldFormatsObj from './field_formats.devdocs.json'; diff --git a/api_docs/fields_metadata.mdx b/api_docs/fields_metadata.mdx index 0a27caa5cb388..faac006668565 100644 --- a/api_docs/fields_metadata.mdx +++ b/api_docs/fields_metadata.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fieldsMetadata title: "fieldsMetadata" image: https://source.unsplash.com/400x175/?github description: API docs for the fieldsMetadata plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fieldsMetadata'] --- import fieldsMetadataObj from './fields_metadata.devdocs.json'; diff --git a/api_docs/file_upload.mdx b/api_docs/file_upload.mdx index 80e85505ce52d..b40c5450cf277 100644 --- a/api_docs/file_upload.mdx +++ b/api_docs/file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fileUpload title: "fileUpload" image: https://source.unsplash.com/400x175/?github description: API docs for the fileUpload plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fileUpload'] --- import fileUploadObj from './file_upload.devdocs.json'; diff --git a/api_docs/files.mdx b/api_docs/files.mdx index b2293153f57bf..1533bb0157c12 100644 --- a/api_docs/files.mdx +++ b/api_docs/files.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/files title: "files" image: https://source.unsplash.com/400x175/?github description: API docs for the files plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'files'] --- import filesObj from './files.devdocs.json'; diff --git a/api_docs/files_management.mdx b/api_docs/files_management.mdx index 6c1b4b229a45a..591f9f3512554 100644 --- a/api_docs/files_management.mdx +++ b/api_docs/files_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/filesManagement title: "filesManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the filesManagement plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'filesManagement'] --- import filesManagementObj from './files_management.devdocs.json'; diff --git a/api_docs/fleet.mdx b/api_docs/fleet.mdx index 84d3ad6837eda..878196bce5ea8 100644 --- a/api_docs/fleet.mdx +++ b/api_docs/fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/fleet title: "fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the fleet plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'fleet'] --- import fleetObj from './fleet.devdocs.json'; diff --git a/api_docs/global_search.mdx b/api_docs/global_search.mdx index cc9ce1336dcc9..3e6daed0dca81 100644 --- a/api_docs/global_search.mdx +++ b/api_docs/global_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/globalSearch title: "globalSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the globalSearch plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'globalSearch'] --- import globalSearchObj from './global_search.devdocs.json'; diff --git a/api_docs/guided_onboarding.mdx b/api_docs/guided_onboarding.mdx index e1451f1948073..56499fc799ed4 100644 --- a/api_docs/guided_onboarding.mdx +++ b/api_docs/guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/guidedOnboarding title: "guidedOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the guidedOnboarding plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'guidedOnboarding'] --- import guidedOnboardingObj from './guided_onboarding.devdocs.json'; diff --git a/api_docs/home.mdx b/api_docs/home.mdx index a689c15c47ab9..d2d1d4bc2ea48 100644 --- a/api_docs/home.mdx +++ b/api_docs/home.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/home title: "home" image: https://source.unsplash.com/400x175/?github description: API docs for the home plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'home'] --- import homeObj from './home.devdocs.json'; diff --git a/api_docs/image_embeddable.mdx b/api_docs/image_embeddable.mdx index 1176005e99c7e..e28009d221159 100644 --- a/api_docs/image_embeddable.mdx +++ b/api_docs/image_embeddable.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/imageEmbeddable title: "imageEmbeddable" image: https://source.unsplash.com/400x175/?github description: API docs for the imageEmbeddable plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'imageEmbeddable'] --- import imageEmbeddableObj from './image_embeddable.devdocs.json'; diff --git a/api_docs/index_lifecycle_management.mdx b/api_docs/index_lifecycle_management.mdx index b4b839eb5c336..9b696f8500762 100644 --- a/api_docs/index_lifecycle_management.mdx +++ b/api_docs/index_lifecycle_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexLifecycleManagement title: "indexLifecycleManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexLifecycleManagement plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexLifecycleManagement'] --- import indexLifecycleManagementObj from './index_lifecycle_management.devdocs.json'; diff --git a/api_docs/index_management.mdx b/api_docs/index_management.mdx index 28bad43e7b19d..4533c6fc4e1d0 100644 --- a/api_docs/index_management.mdx +++ b/api_docs/index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/indexManagement title: "indexManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the indexManagement plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'indexManagement'] --- import indexManagementObj from './index_management.devdocs.json'; diff --git a/api_docs/infra.mdx b/api_docs/infra.mdx index 7407fef64c9af..6cad27c00382a 100644 --- a/api_docs/infra.mdx +++ b/api_docs/infra.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/infra title: "infra" image: https://source.unsplash.com/400x175/?github description: API docs for the infra plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'infra'] --- import infraObj from './infra.devdocs.json'; diff --git a/api_docs/ingest_pipelines.mdx b/api_docs/ingest_pipelines.mdx index c16107e0c8a3f..74c022f35593b 100644 --- a/api_docs/ingest_pipelines.mdx +++ b/api_docs/ingest_pipelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ingestPipelines title: "ingestPipelines" image: https://source.unsplash.com/400x175/?github description: API docs for the ingestPipelines plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ingestPipelines'] --- import ingestPipelinesObj from './ingest_pipelines.devdocs.json'; diff --git a/api_docs/inspector.mdx b/api_docs/inspector.mdx index f88f5ad0c01aa..e13de7f5536b8 100644 --- a/api_docs/inspector.mdx +++ b/api_docs/inspector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/inspector title: "inspector" image: https://source.unsplash.com/400x175/?github description: API docs for the inspector plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'inspector'] --- import inspectorObj from './inspector.devdocs.json'; diff --git a/api_docs/integration_assistant.mdx b/api_docs/integration_assistant.mdx index 5a70a1b9876fc..3841fa26f2be8 100644 --- a/api_docs/integration_assistant.mdx +++ b/api_docs/integration_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/integrationAssistant title: "integrationAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the integrationAssistant plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'integrationAssistant'] --- import integrationAssistantObj from './integration_assistant.devdocs.json'; diff --git a/api_docs/interactive_setup.mdx b/api_docs/interactive_setup.mdx index ec5048dfddf98..83adee7e67870 100644 --- a/api_docs/interactive_setup.mdx +++ b/api_docs/interactive_setup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/interactiveSetup title: "interactiveSetup" image: https://source.unsplash.com/400x175/?github description: API docs for the interactiveSetup plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'interactiveSetup'] --- import interactiveSetupObj from './interactive_setup.devdocs.json'; diff --git a/api_docs/investigate.mdx b/api_docs/investigate.mdx index 1963db52769f5..31538e33c0f11 100644 --- a/api_docs/investigate.mdx +++ b/api_docs/investigate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/investigate title: "investigate" image: https://source.unsplash.com/400x175/?github description: API docs for the investigate plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'investigate'] --- import investigateObj from './investigate.devdocs.json'; diff --git a/api_docs/kbn_ace.mdx b/api_docs/kbn_ace.mdx index abd87a53eeb85..d7454d209d38a 100644 --- a/api_docs/kbn_ace.mdx +++ b/api_docs/kbn_ace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ace title: "@kbn/ace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ace plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ace'] --- import kbnAceObj from './kbn_ace.devdocs.json'; diff --git a/api_docs/kbn_actions_types.mdx b/api_docs/kbn_actions_types.mdx index ea725af2ce7a9..8cdb49b90933a 100644 --- a/api_docs/kbn_actions_types.mdx +++ b/api_docs/kbn_actions_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-actions-types title: "@kbn/actions-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/actions-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/actions-types'] --- import kbnActionsTypesObj from './kbn_actions_types.devdocs.json'; diff --git a/api_docs/kbn_aiops_components.mdx b/api_docs/kbn_aiops_components.mdx index eff4a9084c4b4..f96c4535f1122 100644 --- a/api_docs/kbn_aiops_components.mdx +++ b/api_docs/kbn_aiops_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-components title: "@kbn/aiops-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-components plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-components'] --- import kbnAiopsComponentsObj from './kbn_aiops_components.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_pattern_analysis.mdx b/api_docs/kbn_aiops_log_pattern_analysis.mdx index ff1ec9fa9e73d..ca39ac8051e10 100644 --- a/api_docs/kbn_aiops_log_pattern_analysis.mdx +++ b/api_docs/kbn_aiops_log_pattern_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-pattern-analysis title: "@kbn/aiops-log-pattern-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-pattern-analysis plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-pattern-analysis'] --- import kbnAiopsLogPatternAnalysisObj from './kbn_aiops_log_pattern_analysis.devdocs.json'; diff --git a/api_docs/kbn_aiops_log_rate_analysis.mdx b/api_docs/kbn_aiops_log_rate_analysis.mdx index 794d739d88c95..a26f1fd924138 100644 --- a/api_docs/kbn_aiops_log_rate_analysis.mdx +++ b/api_docs/kbn_aiops_log_rate_analysis.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-aiops-log-rate-analysis title: "@kbn/aiops-log-rate-analysis" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/aiops-log-rate-analysis plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/aiops-log-rate-analysis'] --- import kbnAiopsLogRateAnalysisObj from './kbn_aiops_log_rate_analysis.devdocs.json'; diff --git a/api_docs/kbn_alerting_api_integration_helpers.mdx b/api_docs/kbn_alerting_api_integration_helpers.mdx index b0150d9ed1116..6de793df55de1 100644 --- a/api_docs/kbn_alerting_api_integration_helpers.mdx +++ b/api_docs/kbn_alerting_api_integration_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-api-integration-helpers title: "@kbn/alerting-api-integration-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-api-integration-helpers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-api-integration-helpers'] --- import kbnAlertingApiIntegrationHelpersObj from './kbn_alerting_api_integration_helpers.devdocs.json'; diff --git a/api_docs/kbn_alerting_comparators.mdx b/api_docs/kbn_alerting_comparators.mdx index 7d8591c4dff2b..71b3b357e38a2 100644 --- a/api_docs/kbn_alerting_comparators.mdx +++ b/api_docs/kbn_alerting_comparators.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-comparators title: "@kbn/alerting-comparators" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-comparators plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-comparators'] --- import kbnAlertingComparatorsObj from './kbn_alerting_comparators.devdocs.json'; diff --git a/api_docs/kbn_alerting_state_types.mdx b/api_docs/kbn_alerting_state_types.mdx index 36be974c5a293..91bc0afd721e8 100644 --- a/api_docs/kbn_alerting_state_types.mdx +++ b/api_docs/kbn_alerting_state_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-state-types title: "@kbn/alerting-state-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-state-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-state-types'] --- import kbnAlertingStateTypesObj from './kbn_alerting_state_types.devdocs.json'; diff --git a/api_docs/kbn_alerting_types.mdx b/api_docs/kbn_alerting_types.mdx index aeb1f64e12772..1729db6f15bab 100644 --- a/api_docs/kbn_alerting_types.mdx +++ b/api_docs/kbn_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerting-types title: "@kbn/alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerting-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerting-types'] --- import kbnAlertingTypesObj from './kbn_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_alerts_as_data_utils.mdx b/api_docs/kbn_alerts_as_data_utils.mdx index 3cb1343c59103..4c58645535eaf 100644 --- a/api_docs/kbn_alerts_as_data_utils.mdx +++ b/api_docs/kbn_alerts_as_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-as-data-utils title: "@kbn/alerts-as-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-as-data-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-as-data-utils'] --- import kbnAlertsAsDataUtilsObj from './kbn_alerts_as_data_utils.devdocs.json'; diff --git a/api_docs/kbn_alerts_ui_shared.mdx b/api_docs/kbn_alerts_ui_shared.mdx index a1b9de6236c45..4e8a810fbbc29 100644 --- a/api_docs/kbn_alerts_ui_shared.mdx +++ b/api_docs/kbn_alerts_ui_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-alerts-ui-shared title: "@kbn/alerts-ui-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/alerts-ui-shared plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/alerts-ui-shared'] --- import kbnAlertsUiSharedObj from './kbn_alerts_ui_shared.devdocs.json'; diff --git a/api_docs/kbn_analytics.mdx b/api_docs/kbn_analytics.mdx index 86318835796d3..87faa2d3adb9f 100644 --- a/api_docs/kbn_analytics.mdx +++ b/api_docs/kbn_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics title: "@kbn/analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics'] --- import kbnAnalyticsObj from './kbn_analytics.devdocs.json'; diff --git a/api_docs/kbn_analytics_collection_utils.mdx b/api_docs/kbn_analytics_collection_utils.mdx index 4a1f7b47d1e48..b86d1f742c7c7 100644 --- a/api_docs/kbn_analytics_collection_utils.mdx +++ b/api_docs/kbn_analytics_collection_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-analytics-collection-utils title: "@kbn/analytics-collection-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/analytics-collection-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/analytics-collection-utils'] --- import kbnAnalyticsCollectionUtilsObj from './kbn_analytics_collection_utils.devdocs.json'; diff --git a/api_docs/kbn_apm_config_loader.mdx b/api_docs/kbn_apm_config_loader.mdx index 029027b8a5b04..590f90cd70c1a 100644 --- a/api_docs/kbn_apm_config_loader.mdx +++ b/api_docs/kbn_apm_config_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-config-loader title: "@kbn/apm-config-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-config-loader plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-config-loader'] --- import kbnApmConfigLoaderObj from './kbn_apm_config_loader.devdocs.json'; diff --git a/api_docs/kbn_apm_data_view.mdx b/api_docs/kbn_apm_data_view.mdx index 3bb4612e55ecc..b37a9e175ccea 100644 --- a/api_docs/kbn_apm_data_view.mdx +++ b/api_docs/kbn_apm_data_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-data-view title: "@kbn/apm-data-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-data-view plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-data-view'] --- import kbnApmDataViewObj from './kbn_apm_data_view.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace.mdx b/api_docs/kbn_apm_synthtrace.mdx index 24e6aa68f9a05..d597ff4b9df6e 100644 --- a/api_docs/kbn_apm_synthtrace.mdx +++ b/api_docs/kbn_apm_synthtrace.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace title: "@kbn/apm-synthtrace" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace'] --- import kbnApmSynthtraceObj from './kbn_apm_synthtrace.devdocs.json'; diff --git a/api_docs/kbn_apm_synthtrace_client.mdx b/api_docs/kbn_apm_synthtrace_client.mdx index 88101d196d0d3..310b82c235b01 100644 --- a/api_docs/kbn_apm_synthtrace_client.mdx +++ b/api_docs/kbn_apm_synthtrace_client.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-synthtrace-client title: "@kbn/apm-synthtrace-client" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-synthtrace-client plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-synthtrace-client'] --- import kbnApmSynthtraceClientObj from './kbn_apm_synthtrace_client.devdocs.json'; diff --git a/api_docs/kbn_apm_utils.mdx b/api_docs/kbn_apm_utils.mdx index a66a306d2acda..d0bfdaeba168b 100644 --- a/api_docs/kbn_apm_utils.mdx +++ b/api_docs/kbn_apm_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-apm-utils title: "@kbn/apm-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/apm-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/apm-utils'] --- import kbnApmUtilsObj from './kbn_apm_utils.devdocs.json'; diff --git a/api_docs/kbn_axe_config.mdx b/api_docs/kbn_axe_config.mdx index 3e3948573f3f8..362cc53a01729 100644 --- a/api_docs/kbn_axe_config.mdx +++ b/api_docs/kbn_axe_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-axe-config title: "@kbn/axe-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/axe-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/axe-config'] --- import kbnAxeConfigObj from './kbn_axe_config.devdocs.json'; diff --git a/api_docs/kbn_bfetch_error.mdx b/api_docs/kbn_bfetch_error.mdx index 0938994a490da..81d0db5a518ad 100644 --- a/api_docs/kbn_bfetch_error.mdx +++ b/api_docs/kbn_bfetch_error.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-bfetch-error title: "@kbn/bfetch-error" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/bfetch-error plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/bfetch-error'] --- import kbnBfetchErrorObj from './kbn_bfetch_error.devdocs.json'; diff --git a/api_docs/kbn_calculate_auto.mdx b/api_docs/kbn_calculate_auto.mdx index fdad547a55a74..060e29fed34cb 100644 --- a/api_docs/kbn_calculate_auto.mdx +++ b/api_docs/kbn_calculate_auto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-auto title: "@kbn/calculate-auto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-auto plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-auto'] --- import kbnCalculateAutoObj from './kbn_calculate_auto.devdocs.json'; diff --git a/api_docs/kbn_calculate_width_from_char_count.mdx b/api_docs/kbn_calculate_width_from_char_count.mdx index bd6a49a1c815c..2349c07b01c2d 100644 --- a/api_docs/kbn_calculate_width_from_char_count.mdx +++ b/api_docs/kbn_calculate_width_from_char_count.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-calculate-width-from-char-count title: "@kbn/calculate-width-from-char-count" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/calculate-width-from-char-count plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/calculate-width-from-char-count'] --- import kbnCalculateWidthFromCharCountObj from './kbn_calculate_width_from_char_count.devdocs.json'; diff --git a/api_docs/kbn_cases_components.mdx b/api_docs/kbn_cases_components.mdx index 03430ffccae61..a519ef30e7cbd 100644 --- a/api_docs/kbn_cases_components.mdx +++ b/api_docs/kbn_cases_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cases-components title: "@kbn/cases-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cases-components plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cases-components'] --- import kbnCasesComponentsObj from './kbn_cases_components.devdocs.json'; diff --git a/api_docs/kbn_cell_actions.mdx b/api_docs/kbn_cell_actions.mdx index 6da52d4d8973b..32ca109fcc4ab 100644 --- a/api_docs/kbn_cell_actions.mdx +++ b/api_docs/kbn_cell_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cell-actions title: "@kbn/cell-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cell-actions plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cell-actions'] --- import kbnCellActionsObj from './kbn_cell_actions.devdocs.json'; diff --git a/api_docs/kbn_chart_expressions_common.mdx b/api_docs/kbn_chart_expressions_common.mdx index 84735c77e1854..9f6df7bf76ea5 100644 --- a/api_docs/kbn_chart_expressions_common.mdx +++ b/api_docs/kbn_chart_expressions_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-expressions-common title: "@kbn/chart-expressions-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-expressions-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-expressions-common'] --- import kbnChartExpressionsCommonObj from './kbn_chart_expressions_common.devdocs.json'; diff --git a/api_docs/kbn_chart_icons.mdx b/api_docs/kbn_chart_icons.mdx index 1099bcff9685e..97db00b5526d9 100644 --- a/api_docs/kbn_chart_icons.mdx +++ b/api_docs/kbn_chart_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-chart-icons title: "@kbn/chart-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/chart-icons plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/chart-icons'] --- import kbnChartIconsObj from './kbn_chart_icons.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_core.mdx b/api_docs/kbn_ci_stats_core.mdx index 26572da1fca0f..00d45e078cea5 100644 --- a/api_docs/kbn_ci_stats_core.mdx +++ b/api_docs/kbn_ci_stats_core.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-core title: "@kbn/ci-stats-core" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-core plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-core'] --- import kbnCiStatsCoreObj from './kbn_ci_stats_core.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_performance_metrics.mdx b/api_docs/kbn_ci_stats_performance_metrics.mdx index d97bb26f2cd7d..449e5aa0aa25e 100644 --- a/api_docs/kbn_ci_stats_performance_metrics.mdx +++ b/api_docs/kbn_ci_stats_performance_metrics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-performance-metrics title: "@kbn/ci-stats-performance-metrics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-performance-metrics plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-performance-metrics'] --- import kbnCiStatsPerformanceMetricsObj from './kbn_ci_stats_performance_metrics.devdocs.json'; diff --git a/api_docs/kbn_ci_stats_reporter.mdx b/api_docs/kbn_ci_stats_reporter.mdx index 4b8cd4a7dbd15..53bfc9d5761a0 100644 --- a/api_docs/kbn_ci_stats_reporter.mdx +++ b/api_docs/kbn_ci_stats_reporter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ci-stats-reporter title: "@kbn/ci-stats-reporter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ci-stats-reporter plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ci-stats-reporter'] --- import kbnCiStatsReporterObj from './kbn_ci_stats_reporter.devdocs.json'; diff --git a/api_docs/kbn_cli_dev_mode.mdx b/api_docs/kbn_cli_dev_mode.mdx index f31d8b65ded80..ec72a50bd3116 100644 --- a/api_docs/kbn_cli_dev_mode.mdx +++ b/api_docs/kbn_cli_dev_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cli-dev-mode title: "@kbn/cli-dev-mode" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cli-dev-mode plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cli-dev-mode'] --- import kbnCliDevModeObj from './kbn_cli_dev_mode.devdocs.json'; diff --git a/api_docs/kbn_code_editor.mdx b/api_docs/kbn_code_editor.mdx index a1f046eb47840..390efaccf375b 100644 --- a/api_docs/kbn_code_editor.mdx +++ b/api_docs/kbn_code_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor title: "@kbn/code-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor'] --- import kbnCodeEditorObj from './kbn_code_editor.devdocs.json'; diff --git a/api_docs/kbn_code_editor_mock.mdx b/api_docs/kbn_code_editor_mock.mdx index 0d749bfc88ca5..a91531a61adf9 100644 --- a/api_docs/kbn_code_editor_mock.mdx +++ b/api_docs/kbn_code_editor_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-editor-mock title: "@kbn/code-editor-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-editor-mock plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-editor-mock'] --- import kbnCodeEditorMockObj from './kbn_code_editor_mock.devdocs.json'; diff --git a/api_docs/kbn_code_owners.mdx b/api_docs/kbn_code_owners.mdx index 9c6bf7b5f2300..a38efab35b8cf 100644 --- a/api_docs/kbn_code_owners.mdx +++ b/api_docs/kbn_code_owners.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-code-owners title: "@kbn/code-owners" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/code-owners plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/code-owners'] --- import kbnCodeOwnersObj from './kbn_code_owners.devdocs.json'; diff --git a/api_docs/kbn_coloring.mdx b/api_docs/kbn_coloring.mdx index 779045f856559..c1e1ab2988962 100644 --- a/api_docs/kbn_coloring.mdx +++ b/api_docs/kbn_coloring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-coloring title: "@kbn/coloring" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/coloring plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/coloring'] --- import kbnColoringObj from './kbn_coloring.devdocs.json'; diff --git a/api_docs/kbn_config.mdx b/api_docs/kbn_config.mdx index 04aea81959d4f..3ab0d365180f6 100644 --- a/api_docs/kbn_config.mdx +++ b/api_docs/kbn_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config title: "@kbn/config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config'] --- import kbnConfigObj from './kbn_config.devdocs.json'; diff --git a/api_docs/kbn_config_mocks.mdx b/api_docs/kbn_config_mocks.mdx index 86cf94b989283..e96faaa0ef9b4 100644 --- a/api_docs/kbn_config_mocks.mdx +++ b/api_docs/kbn_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-mocks title: "@kbn/config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-mocks'] --- import kbnConfigMocksObj from './kbn_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_config_schema.mdx b/api_docs/kbn_config_schema.mdx index 264badf08232a..4d66c3732f4f1 100644 --- a/api_docs/kbn_config_schema.mdx +++ b/api_docs/kbn_config_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-config-schema title: "@kbn/config-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/config-schema plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/config-schema'] --- import kbnConfigSchemaObj from './kbn_config_schema.devdocs.json'; diff --git a/api_docs/kbn_content_management_content_editor.mdx b/api_docs/kbn_content_management_content_editor.mdx index 98a38d120f25d..93d9d06f0e809 100644 --- a/api_docs/kbn_content_management_content_editor.mdx +++ b/api_docs/kbn_content_management_content_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-content-editor title: "@kbn/content-management-content-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-content-editor plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-content-editor'] --- import kbnContentManagementContentEditorObj from './kbn_content_management_content_editor.devdocs.json'; diff --git a/api_docs/kbn_content_management_tabbed_table_list_view.mdx b/api_docs/kbn_content_management_tabbed_table_list_view.mdx index 1f9f099e8c655..2f8b037786fbf 100644 --- a/api_docs/kbn_content_management_tabbed_table_list_view.mdx +++ b/api_docs/kbn_content_management_tabbed_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-tabbed-table-list-view title: "@kbn/content-management-tabbed-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-tabbed-table-list-view plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-tabbed-table-list-view'] --- import kbnContentManagementTabbedTableListViewObj from './kbn_content_management_tabbed_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view.mdx b/api_docs/kbn_content_management_table_list_view.mdx index 2d870c3943818..ce8de97333afd 100644 --- a/api_docs/kbn_content_management_table_list_view.mdx +++ b/api_docs/kbn_content_management_table_list_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view title: "@kbn/content-management-table-list-view" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view'] --- import kbnContentManagementTableListViewObj from './kbn_content_management_table_list_view.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_common.mdx b/api_docs/kbn_content_management_table_list_view_common.mdx index 4eea179826ddd..5bb5732e5e8b2 100644 --- a/api_docs/kbn_content_management_table_list_view_common.mdx +++ b/api_docs/kbn_content_management_table_list_view_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-common title: "@kbn/content-management-table-list-view-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-common'] --- import kbnContentManagementTableListViewCommonObj from './kbn_content_management_table_list_view_common.devdocs.json'; diff --git a/api_docs/kbn_content_management_table_list_view_table.mdx b/api_docs/kbn_content_management_table_list_view_table.mdx index 0525beb90b6bc..2d0b4c7f495a1 100644 --- a/api_docs/kbn_content_management_table_list_view_table.mdx +++ b/api_docs/kbn_content_management_table_list_view_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-table-list-view-table title: "@kbn/content-management-table-list-view-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-table-list-view-table plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-table-list-view-table'] --- import kbnContentManagementTableListViewTableObj from './kbn_content_management_table_list_view_table.devdocs.json'; diff --git a/api_docs/kbn_content_management_user_profiles.mdx b/api_docs/kbn_content_management_user_profiles.mdx index 39c978a05318e..93ec961ff480d 100644 --- a/api_docs/kbn_content_management_user_profiles.mdx +++ b/api_docs/kbn_content_management_user_profiles.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-user-profiles title: "@kbn/content-management-user-profiles" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-user-profiles plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-user-profiles'] --- import kbnContentManagementUserProfilesObj from './kbn_content_management_user_profiles.devdocs.json'; diff --git a/api_docs/kbn_content_management_utils.mdx b/api_docs/kbn_content_management_utils.mdx index aff4936f874d9..5edb408b71e8a 100644 --- a/api_docs/kbn_content_management_utils.mdx +++ b/api_docs/kbn_content_management_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-content-management-utils title: "@kbn/content-management-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/content-management-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/content-management-utils'] --- import kbnContentManagementUtilsObj from './kbn_content_management_utils.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser.devdocs.json b/api_docs/kbn_core_analytics_browser.devdocs.json index 7f19ef23a3e2d..39750c189b184 100644 --- a/api_docs/kbn_core_analytics_browser.devdocs.json +++ b/api_docs/kbn_core_analytics_browser.devdocs.json @@ -731,6 +731,22 @@ "plugin": "elasticAssistant", "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, { "plugin": "globalSearchBar", "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" @@ -907,10 +923,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" @@ -1183,6 +1195,38 @@ "plugin": "security", "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, { "plugin": "apm", "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" diff --git a/api_docs/kbn_core_analytics_browser.mdx b/api_docs/kbn_core_analytics_browser.mdx index 2adc2b868833d..9e3926f63fd75 100644 --- a/api_docs/kbn_core_analytics_browser.mdx +++ b/api_docs/kbn_core_analytics_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser title: "@kbn/core-analytics-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser'] --- import kbnCoreAnalyticsBrowserObj from './kbn_core_analytics_browser.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_internal.mdx b/api_docs/kbn_core_analytics_browser_internal.mdx index 64593528107eb..7a7e41dcfbc9c 100644 --- a/api_docs/kbn_core_analytics_browser_internal.mdx +++ b/api_docs/kbn_core_analytics_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-internal title: "@kbn/core-analytics-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-internal'] --- import kbnCoreAnalyticsBrowserInternalObj from './kbn_core_analytics_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_browser_mocks.mdx b/api_docs/kbn_core_analytics_browser_mocks.mdx index 31592bcfd9d68..27f69739ff8f3 100644 --- a/api_docs/kbn_core_analytics_browser_mocks.mdx +++ b/api_docs/kbn_core_analytics_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-browser-mocks title: "@kbn/core-analytics-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-browser-mocks'] --- import kbnCoreAnalyticsBrowserMocksObj from './kbn_core_analytics_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server.devdocs.json b/api_docs/kbn_core_analytics_server.devdocs.json index 5c4760eb2c883..d65f4d6171a88 100644 --- a/api_docs/kbn_core_analytics_server.devdocs.json +++ b/api_docs/kbn_core_analytics_server.devdocs.json @@ -731,6 +731,22 @@ "plugin": "elasticAssistant", "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, { "plugin": "globalSearchBar", "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" @@ -907,10 +923,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" @@ -1183,6 +1195,38 @@ "plugin": "security", "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, { "plugin": "apm", "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" diff --git a/api_docs/kbn_core_analytics_server.mdx b/api_docs/kbn_core_analytics_server.mdx index 6d0c931f36913..ef4a46ab4236d 100644 --- a/api_docs/kbn_core_analytics_server.mdx +++ b/api_docs/kbn_core_analytics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server title: "@kbn/core-analytics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server'] --- import kbnCoreAnalyticsServerObj from './kbn_core_analytics_server.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_internal.mdx b/api_docs/kbn_core_analytics_server_internal.mdx index 9944c753972ba..539d99683f706 100644 --- a/api_docs/kbn_core_analytics_server_internal.mdx +++ b/api_docs/kbn_core_analytics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-internal title: "@kbn/core-analytics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-internal'] --- import kbnCoreAnalyticsServerInternalObj from './kbn_core_analytics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_analytics_server_mocks.mdx b/api_docs/kbn_core_analytics_server_mocks.mdx index bf70f65d079f1..4c9c4c06d7f8c 100644 --- a/api_docs/kbn_core_analytics_server_mocks.mdx +++ b/api_docs/kbn_core_analytics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-analytics-server-mocks title: "@kbn/core-analytics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-analytics-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-analytics-server-mocks'] --- import kbnCoreAnalyticsServerMocksObj from './kbn_core_analytics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser.mdx b/api_docs/kbn_core_application_browser.mdx index 204b728e5392a..221092861f17f 100644 --- a/api_docs/kbn_core_application_browser.mdx +++ b/api_docs/kbn_core_application_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser title: "@kbn/core-application-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser'] --- import kbnCoreApplicationBrowserObj from './kbn_core_application_browser.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_internal.mdx b/api_docs/kbn_core_application_browser_internal.mdx index 7516893ed6f8a..ea8f1ee3a473b 100644 --- a/api_docs/kbn_core_application_browser_internal.mdx +++ b/api_docs/kbn_core_application_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-internal title: "@kbn/core-application-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-internal'] --- import kbnCoreApplicationBrowserInternalObj from './kbn_core_application_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_application_browser_mocks.mdx b/api_docs/kbn_core_application_browser_mocks.mdx index 700c2f4a467f1..a34b007d00008 100644 --- a/api_docs/kbn_core_application_browser_mocks.mdx +++ b/api_docs/kbn_core_application_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-browser-mocks title: "@kbn/core-application-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-browser-mocks'] --- import kbnCoreApplicationBrowserMocksObj from './kbn_core_application_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_application_common.mdx b/api_docs/kbn_core_application_common.mdx index f4094609e083b..04a3059c5847e 100644 --- a/api_docs/kbn_core_application_common.mdx +++ b/api_docs/kbn_core_application_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-application-common title: "@kbn/core-application-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-application-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-application-common'] --- import kbnCoreApplicationCommonObj from './kbn_core_application_common.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_internal.mdx b/api_docs/kbn_core_apps_browser_internal.mdx index 876dd82081ce1..097710a940f28 100644 --- a/api_docs/kbn_core_apps_browser_internal.mdx +++ b/api_docs/kbn_core_apps_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-internal title: "@kbn/core-apps-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-internal'] --- import kbnCoreAppsBrowserInternalObj from './kbn_core_apps_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_apps_browser_mocks.mdx b/api_docs/kbn_core_apps_browser_mocks.mdx index 02f02263a5a7d..3564a272e97b9 100644 --- a/api_docs/kbn_core_apps_browser_mocks.mdx +++ b/api_docs/kbn_core_apps_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-browser-mocks title: "@kbn/core-apps-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-browser-mocks'] --- import kbnCoreAppsBrowserMocksObj from './kbn_core_apps_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_apps_server_internal.mdx b/api_docs/kbn_core_apps_server_internal.mdx index 65dbc90710661..7997672d6ce09 100644 --- a/api_docs/kbn_core_apps_server_internal.mdx +++ b/api_docs/kbn_core_apps_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-apps-server-internal title: "@kbn/core-apps-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-apps-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-apps-server-internal'] --- import kbnCoreAppsServerInternalObj from './kbn_core_apps_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_browser_mocks.mdx b/api_docs/kbn_core_base_browser_mocks.mdx index 1ef6677142632..825e58de270c4 100644 --- a/api_docs/kbn_core_base_browser_mocks.mdx +++ b/api_docs/kbn_core_base_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-browser-mocks title: "@kbn/core-base-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-browser-mocks'] --- import kbnCoreBaseBrowserMocksObj from './kbn_core_base_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_base_common.mdx b/api_docs/kbn_core_base_common.mdx index a71c9027827a2..b16096e887e54 100644 --- a/api_docs/kbn_core_base_common.mdx +++ b/api_docs/kbn_core_base_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-common title: "@kbn/core-base-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-common'] --- import kbnCoreBaseCommonObj from './kbn_core_base_common.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_internal.mdx b/api_docs/kbn_core_base_server_internal.mdx index 9c7e35483d920..503df4cd3bd6f 100644 --- a/api_docs/kbn_core_base_server_internal.mdx +++ b/api_docs/kbn_core_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-internal title: "@kbn/core-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-internal'] --- import kbnCoreBaseServerInternalObj from './kbn_core_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_base_server_mocks.mdx b/api_docs/kbn_core_base_server_mocks.mdx index 63d72714a8143..b171839b6948d 100644 --- a/api_docs/kbn_core_base_server_mocks.mdx +++ b/api_docs/kbn_core_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-base-server-mocks title: "@kbn/core-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-base-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-base-server-mocks'] --- import kbnCoreBaseServerMocksObj from './kbn_core_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_browser_mocks.mdx b/api_docs/kbn_core_capabilities_browser_mocks.mdx index c66a5c67511c1..e2008bd13c888 100644 --- a/api_docs/kbn_core_capabilities_browser_mocks.mdx +++ b/api_docs/kbn_core_capabilities_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-browser-mocks title: "@kbn/core-capabilities-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-browser-mocks'] --- import kbnCoreCapabilitiesBrowserMocksObj from './kbn_core_capabilities_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_common.mdx b/api_docs/kbn_core_capabilities_common.mdx index 105cbfd180048..77854db23aa70 100644 --- a/api_docs/kbn_core_capabilities_common.mdx +++ b/api_docs/kbn_core_capabilities_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-common title: "@kbn/core-capabilities-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-common'] --- import kbnCoreCapabilitiesCommonObj from './kbn_core_capabilities_common.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server.mdx b/api_docs/kbn_core_capabilities_server.mdx index fe73f11a83d6e..07d9e92b3d1f8 100644 --- a/api_docs/kbn_core_capabilities_server.mdx +++ b/api_docs/kbn_core_capabilities_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server title: "@kbn/core-capabilities-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server'] --- import kbnCoreCapabilitiesServerObj from './kbn_core_capabilities_server.devdocs.json'; diff --git a/api_docs/kbn_core_capabilities_server_mocks.mdx b/api_docs/kbn_core_capabilities_server_mocks.mdx index a4d21787f2b99..f7557b4c3a948 100644 --- a/api_docs/kbn_core_capabilities_server_mocks.mdx +++ b/api_docs/kbn_core_capabilities_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-capabilities-server-mocks title: "@kbn/core-capabilities-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-capabilities-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-capabilities-server-mocks'] --- import kbnCoreCapabilitiesServerMocksObj from './kbn_core_capabilities_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser.mdx b/api_docs/kbn_core_chrome_browser.mdx index 2eb8c8861b427..bb44696cad63d 100644 --- a/api_docs/kbn_core_chrome_browser.mdx +++ b/api_docs/kbn_core_chrome_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser title: "@kbn/core-chrome-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser'] --- import kbnCoreChromeBrowserObj from './kbn_core_chrome_browser.devdocs.json'; diff --git a/api_docs/kbn_core_chrome_browser_mocks.mdx b/api_docs/kbn_core_chrome_browser_mocks.mdx index b30dc71ae5ad8..29c418e82a055 100644 --- a/api_docs/kbn_core_chrome_browser_mocks.mdx +++ b/api_docs/kbn_core_chrome_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-chrome-browser-mocks title: "@kbn/core-chrome-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-chrome-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-chrome-browser-mocks'] --- import kbnCoreChromeBrowserMocksObj from './kbn_core_chrome_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_config_server_internal.mdx b/api_docs/kbn_core_config_server_internal.mdx index 00b98a7cf8d64..6451a22568a46 100644 --- a/api_docs/kbn_core_config_server_internal.mdx +++ b/api_docs/kbn_core_config_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-config-server-internal title: "@kbn/core-config-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-config-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-config-server-internal'] --- import kbnCoreConfigServerInternalObj from './kbn_core_config_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser.mdx b/api_docs/kbn_core_custom_branding_browser.mdx index bf0b92b433f47..b4b06df21502b 100644 --- a/api_docs/kbn_core_custom_branding_browser.mdx +++ b/api_docs/kbn_core_custom_branding_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser title: "@kbn/core-custom-branding-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser'] --- import kbnCoreCustomBrandingBrowserObj from './kbn_core_custom_branding_browser.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_internal.mdx b/api_docs/kbn_core_custom_branding_browser_internal.mdx index a8ea6b0e124c5..6b81b6423753a 100644 --- a/api_docs/kbn_core_custom_branding_browser_internal.mdx +++ b/api_docs/kbn_core_custom_branding_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-internal title: "@kbn/core-custom-branding-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-internal'] --- import kbnCoreCustomBrandingBrowserInternalObj from './kbn_core_custom_branding_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_browser_mocks.mdx b/api_docs/kbn_core_custom_branding_browser_mocks.mdx index c4b392b2b3f64..65c8d0cab5686 100644 --- a/api_docs/kbn_core_custom_branding_browser_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-browser-mocks title: "@kbn/core-custom-branding-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-browser-mocks'] --- import kbnCoreCustomBrandingBrowserMocksObj from './kbn_core_custom_branding_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_common.mdx b/api_docs/kbn_core_custom_branding_common.mdx index af5939bdd4a92..138ffd506865d 100644 --- a/api_docs/kbn_core_custom_branding_common.mdx +++ b/api_docs/kbn_core_custom_branding_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-common title: "@kbn/core-custom-branding-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-common'] --- import kbnCoreCustomBrandingCommonObj from './kbn_core_custom_branding_common.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server.mdx b/api_docs/kbn_core_custom_branding_server.mdx index 23dd0e90b9090..10fde66dc8609 100644 --- a/api_docs/kbn_core_custom_branding_server.mdx +++ b/api_docs/kbn_core_custom_branding_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server title: "@kbn/core-custom-branding-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server'] --- import kbnCoreCustomBrandingServerObj from './kbn_core_custom_branding_server.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_internal.mdx b/api_docs/kbn_core_custom_branding_server_internal.mdx index 87018781af486..4aaed34e6b773 100644 --- a/api_docs/kbn_core_custom_branding_server_internal.mdx +++ b/api_docs/kbn_core_custom_branding_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-internal title: "@kbn/core-custom-branding-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-internal'] --- import kbnCoreCustomBrandingServerInternalObj from './kbn_core_custom_branding_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_custom_branding_server_mocks.mdx b/api_docs/kbn_core_custom_branding_server_mocks.mdx index c084420fc789e..5a8aeaed5f10f 100644 --- a/api_docs/kbn_core_custom_branding_server_mocks.mdx +++ b/api_docs/kbn_core_custom_branding_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-custom-branding-server-mocks title: "@kbn/core-custom-branding-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-custom-branding-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-custom-branding-server-mocks'] --- import kbnCoreCustomBrandingServerMocksObj from './kbn_core_custom_branding_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser.mdx b/api_docs/kbn_core_deprecations_browser.mdx index cbd67dc50b680..93784931295a7 100644 --- a/api_docs/kbn_core_deprecations_browser.mdx +++ b/api_docs/kbn_core_deprecations_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser title: "@kbn/core-deprecations-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser'] --- import kbnCoreDeprecationsBrowserObj from './kbn_core_deprecations_browser.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_internal.mdx b/api_docs/kbn_core_deprecations_browser_internal.mdx index 6747d00759b8d..9b1601b6ad638 100644 --- a/api_docs/kbn_core_deprecations_browser_internal.mdx +++ b/api_docs/kbn_core_deprecations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-internal title: "@kbn/core-deprecations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-internal'] --- import kbnCoreDeprecationsBrowserInternalObj from './kbn_core_deprecations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_browser_mocks.mdx b/api_docs/kbn_core_deprecations_browser_mocks.mdx index 48c3300d7623d..9fc116833ef5e 100644 --- a/api_docs/kbn_core_deprecations_browser_mocks.mdx +++ b/api_docs/kbn_core_deprecations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-browser-mocks title: "@kbn/core-deprecations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-browser-mocks'] --- import kbnCoreDeprecationsBrowserMocksObj from './kbn_core_deprecations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_common.mdx b/api_docs/kbn_core_deprecations_common.mdx index ab9056d47548c..550cf07831a4b 100644 --- a/api_docs/kbn_core_deprecations_common.mdx +++ b/api_docs/kbn_core_deprecations_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-common title: "@kbn/core-deprecations-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-common'] --- import kbnCoreDeprecationsCommonObj from './kbn_core_deprecations_common.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server.mdx b/api_docs/kbn_core_deprecations_server.mdx index 75bc9fe57f2fd..e80690275ca77 100644 --- a/api_docs/kbn_core_deprecations_server.mdx +++ b/api_docs/kbn_core_deprecations_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server title: "@kbn/core-deprecations-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server'] --- import kbnCoreDeprecationsServerObj from './kbn_core_deprecations_server.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_internal.mdx b/api_docs/kbn_core_deprecations_server_internal.mdx index b0012fcd602dc..9dd35a615fa8f 100644 --- a/api_docs/kbn_core_deprecations_server_internal.mdx +++ b/api_docs/kbn_core_deprecations_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-internal title: "@kbn/core-deprecations-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-internal'] --- import kbnCoreDeprecationsServerInternalObj from './kbn_core_deprecations_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_deprecations_server_mocks.mdx b/api_docs/kbn_core_deprecations_server_mocks.mdx index ffcc60aa92b55..d514dbb4c3f76 100644 --- a/api_docs/kbn_core_deprecations_server_mocks.mdx +++ b/api_docs/kbn_core_deprecations_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-deprecations-server-mocks title: "@kbn/core-deprecations-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-deprecations-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-deprecations-server-mocks'] --- import kbnCoreDeprecationsServerMocksObj from './kbn_core_deprecations_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser.mdx b/api_docs/kbn_core_doc_links_browser.mdx index 9314a5e3eb1a8..67b1e15581d91 100644 --- a/api_docs/kbn_core_doc_links_browser.mdx +++ b/api_docs/kbn_core_doc_links_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser title: "@kbn/core-doc-links-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser'] --- import kbnCoreDocLinksBrowserObj from './kbn_core_doc_links_browser.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_browser_mocks.mdx b/api_docs/kbn_core_doc_links_browser_mocks.mdx index cbf160d8d3080..2cacdb5c689b7 100644 --- a/api_docs/kbn_core_doc_links_browser_mocks.mdx +++ b/api_docs/kbn_core_doc_links_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-browser-mocks title: "@kbn/core-doc-links-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-browser-mocks'] --- import kbnCoreDocLinksBrowserMocksObj from './kbn_core_doc_links_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server.mdx b/api_docs/kbn_core_doc_links_server.mdx index 29147308f7df5..dd8407f8a224e 100644 --- a/api_docs/kbn_core_doc_links_server.mdx +++ b/api_docs/kbn_core_doc_links_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server title: "@kbn/core-doc-links-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server'] --- import kbnCoreDocLinksServerObj from './kbn_core_doc_links_server.devdocs.json'; diff --git a/api_docs/kbn_core_doc_links_server_mocks.mdx b/api_docs/kbn_core_doc_links_server_mocks.mdx index 53829043e40ea..417f1090ff108 100644 --- a/api_docs/kbn_core_doc_links_server_mocks.mdx +++ b/api_docs/kbn_core_doc_links_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-doc-links-server-mocks title: "@kbn/core-doc-links-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-doc-links-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-doc-links-server-mocks'] --- import kbnCoreDocLinksServerMocksObj from './kbn_core_doc_links_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx index 19cf8e79d068d..8676c82397faa 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-internal title: "@kbn/core-elasticsearch-client-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-internal'] --- import kbnCoreElasticsearchClientServerInternalObj from './kbn_core_elasticsearch_client_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx index c7b1f89c151ad..c567e853ffdd0 100644 --- a/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_client_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-client-server-mocks title: "@kbn/core-elasticsearch-client-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-client-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-client-server-mocks'] --- import kbnCoreElasticsearchClientServerMocksObj from './kbn_core_elasticsearch_client_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server.mdx b/api_docs/kbn_core_elasticsearch_server.mdx index 64c90ee43a750..443e8801939a8 100644 --- a/api_docs/kbn_core_elasticsearch_server.mdx +++ b/api_docs/kbn_core_elasticsearch_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server title: "@kbn/core-elasticsearch-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server'] --- import kbnCoreElasticsearchServerObj from './kbn_core_elasticsearch_server.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_internal.mdx b/api_docs/kbn_core_elasticsearch_server_internal.mdx index 48f395a16f1db..fcda7a5f21026 100644 --- a/api_docs/kbn_core_elasticsearch_server_internal.mdx +++ b/api_docs/kbn_core_elasticsearch_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-internal title: "@kbn/core-elasticsearch-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-internal'] --- import kbnCoreElasticsearchServerInternalObj from './kbn_core_elasticsearch_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_elasticsearch_server_mocks.mdx b/api_docs/kbn_core_elasticsearch_server_mocks.mdx index 5565339907128..b29faf17c9ba3 100644 --- a/api_docs/kbn_core_elasticsearch_server_mocks.mdx +++ b/api_docs/kbn_core_elasticsearch_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-elasticsearch-server-mocks title: "@kbn/core-elasticsearch-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-elasticsearch-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-elasticsearch-server-mocks'] --- import kbnCoreElasticsearchServerMocksObj from './kbn_core_elasticsearch_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_internal.mdx b/api_docs/kbn_core_environment_server_internal.mdx index e03a218fdb0b8..dde4b3c3a57a2 100644 --- a/api_docs/kbn_core_environment_server_internal.mdx +++ b/api_docs/kbn_core_environment_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-internal title: "@kbn/core-environment-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-internal'] --- import kbnCoreEnvironmentServerInternalObj from './kbn_core_environment_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_environment_server_mocks.mdx b/api_docs/kbn_core_environment_server_mocks.mdx index 9d18545cc2a5c..a084cd9a24082 100644 --- a/api_docs/kbn_core_environment_server_mocks.mdx +++ b/api_docs/kbn_core_environment_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-environment-server-mocks title: "@kbn/core-environment-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-environment-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-environment-server-mocks'] --- import kbnCoreEnvironmentServerMocksObj from './kbn_core_environment_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser.mdx b/api_docs/kbn_core_execution_context_browser.mdx index f2a1a3a306090..d2892d0a83735 100644 --- a/api_docs/kbn_core_execution_context_browser.mdx +++ b/api_docs/kbn_core_execution_context_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser title: "@kbn/core-execution-context-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser'] --- import kbnCoreExecutionContextBrowserObj from './kbn_core_execution_context_browser.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_internal.mdx b/api_docs/kbn_core_execution_context_browser_internal.mdx index 489294f6cfab8..c9b48238a1288 100644 --- a/api_docs/kbn_core_execution_context_browser_internal.mdx +++ b/api_docs/kbn_core_execution_context_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-internal title: "@kbn/core-execution-context-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-internal'] --- import kbnCoreExecutionContextBrowserInternalObj from './kbn_core_execution_context_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_browser_mocks.mdx b/api_docs/kbn_core_execution_context_browser_mocks.mdx index 24eb957479991..071f9f876f6be 100644 --- a/api_docs/kbn_core_execution_context_browser_mocks.mdx +++ b/api_docs/kbn_core_execution_context_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-browser-mocks title: "@kbn/core-execution-context-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-browser-mocks'] --- import kbnCoreExecutionContextBrowserMocksObj from './kbn_core_execution_context_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_common.mdx b/api_docs/kbn_core_execution_context_common.mdx index 73557d75597ff..4eb83e0e0790f 100644 --- a/api_docs/kbn_core_execution_context_common.mdx +++ b/api_docs/kbn_core_execution_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-common title: "@kbn/core-execution-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-common'] --- import kbnCoreExecutionContextCommonObj from './kbn_core_execution_context_common.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server.mdx b/api_docs/kbn_core_execution_context_server.mdx index 57cf32fc2fb4f..9802ffa0379b3 100644 --- a/api_docs/kbn_core_execution_context_server.mdx +++ b/api_docs/kbn_core_execution_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server title: "@kbn/core-execution-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server'] --- import kbnCoreExecutionContextServerObj from './kbn_core_execution_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_internal.mdx b/api_docs/kbn_core_execution_context_server_internal.mdx index 9fb5c7fd802e8..531d1ab56f7af 100644 --- a/api_docs/kbn_core_execution_context_server_internal.mdx +++ b/api_docs/kbn_core_execution_context_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-internal title: "@kbn/core-execution-context-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-internal'] --- import kbnCoreExecutionContextServerInternalObj from './kbn_core_execution_context_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_execution_context_server_mocks.mdx b/api_docs/kbn_core_execution_context_server_mocks.mdx index 9381f3287b61d..f58be494fa958 100644 --- a/api_docs/kbn_core_execution_context_server_mocks.mdx +++ b/api_docs/kbn_core_execution_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-execution-context-server-mocks title: "@kbn/core-execution-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-execution-context-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-execution-context-server-mocks'] --- import kbnCoreExecutionContextServerMocksObj from './kbn_core_execution_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser.mdx b/api_docs/kbn_core_fatal_errors_browser.mdx index 7e7544f3b24c5..bf6819d4c2fc1 100644 --- a/api_docs/kbn_core_fatal_errors_browser.mdx +++ b/api_docs/kbn_core_fatal_errors_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser title: "@kbn/core-fatal-errors-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser'] --- import kbnCoreFatalErrorsBrowserObj from './kbn_core_fatal_errors_browser.devdocs.json'; diff --git a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx index f16f340832958..ccdf8d8b861b1 100644 --- a/api_docs/kbn_core_fatal_errors_browser_mocks.mdx +++ b/api_docs/kbn_core_fatal_errors_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-fatal-errors-browser-mocks title: "@kbn/core-fatal-errors-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-fatal-errors-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-fatal-errors-browser-mocks'] --- import kbnCoreFatalErrorsBrowserMocksObj from './kbn_core_fatal_errors_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser.mdx b/api_docs/kbn_core_http_browser.mdx index f2417ebcc4406..1ccd335ef9cf5 100644 --- a/api_docs/kbn_core_http_browser.mdx +++ b/api_docs/kbn_core_http_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser title: "@kbn/core-http-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser'] --- import kbnCoreHttpBrowserObj from './kbn_core_http_browser.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_internal.mdx b/api_docs/kbn_core_http_browser_internal.mdx index d79686b49cb0a..c3221b1de619c 100644 --- a/api_docs/kbn_core_http_browser_internal.mdx +++ b/api_docs/kbn_core_http_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-internal title: "@kbn/core-http-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-internal'] --- import kbnCoreHttpBrowserInternalObj from './kbn_core_http_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_browser_mocks.mdx b/api_docs/kbn_core_http_browser_mocks.mdx index 6964fc72f7f55..2813af7164e71 100644 --- a/api_docs/kbn_core_http_browser_mocks.mdx +++ b/api_docs/kbn_core_http_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-browser-mocks title: "@kbn/core-http-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-browser-mocks'] --- import kbnCoreHttpBrowserMocksObj from './kbn_core_http_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_common.mdx b/api_docs/kbn_core_http_common.mdx index 793283bb287b2..6eec62cf74d4c 100644 --- a/api_docs/kbn_core_http_common.mdx +++ b/api_docs/kbn_core_http_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-common title: "@kbn/core-http-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-common'] --- import kbnCoreHttpCommonObj from './kbn_core_http_common.devdocs.json'; diff --git a/api_docs/kbn_core_http_context_server_mocks.mdx b/api_docs/kbn_core_http_context_server_mocks.mdx index d9e5ea0f55403..5c76803d6b62e 100644 --- a/api_docs/kbn_core_http_context_server_mocks.mdx +++ b/api_docs/kbn_core_http_context_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-context-server-mocks title: "@kbn/core-http-context-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-context-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-context-server-mocks'] --- import kbnCoreHttpContextServerMocksObj from './kbn_core_http_context_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_request_handler_context_server.mdx b/api_docs/kbn_core_http_request_handler_context_server.mdx index 6bc6978fd0c86..c2c3d7eb0950c 100644 --- a/api_docs/kbn_core_http_request_handler_context_server.mdx +++ b/api_docs/kbn_core_http_request_handler_context_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-request-handler-context-server title: "@kbn/core-http-request-handler-context-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-request-handler-context-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-request-handler-context-server'] --- import kbnCoreHttpRequestHandlerContextServerObj from './kbn_core_http_request_handler_context_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server.mdx b/api_docs/kbn_core_http_resources_server.mdx index af970eac350e4..8ab944be3b963 100644 --- a/api_docs/kbn_core_http_resources_server.mdx +++ b/api_docs/kbn_core_http_resources_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server title: "@kbn/core-http-resources-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server'] --- import kbnCoreHttpResourcesServerObj from './kbn_core_http_resources_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_internal.mdx b/api_docs/kbn_core_http_resources_server_internal.mdx index ca451598c8b7c..a3b6878226f1f 100644 --- a/api_docs/kbn_core_http_resources_server_internal.mdx +++ b/api_docs/kbn_core_http_resources_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-internal title: "@kbn/core-http-resources-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-internal'] --- import kbnCoreHttpResourcesServerInternalObj from './kbn_core_http_resources_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_resources_server_mocks.mdx b/api_docs/kbn_core_http_resources_server_mocks.mdx index bc041046b7a03..f7a22f07c5714 100644 --- a/api_docs/kbn_core_http_resources_server_mocks.mdx +++ b/api_docs/kbn_core_http_resources_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-resources-server-mocks title: "@kbn/core-http-resources-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-resources-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-resources-server-mocks'] --- import kbnCoreHttpResourcesServerMocksObj from './kbn_core_http_resources_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_internal.mdx b/api_docs/kbn_core_http_router_server_internal.mdx index 3df41783fe35e..013fb8ee7f3c0 100644 --- a/api_docs/kbn_core_http_router_server_internal.mdx +++ b/api_docs/kbn_core_http_router_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-internal title: "@kbn/core-http-router-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-internal'] --- import kbnCoreHttpRouterServerInternalObj from './kbn_core_http_router_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_router_server_mocks.mdx b/api_docs/kbn_core_http_router_server_mocks.mdx index 028f436ac52b8..9c97eb7183e30 100644 --- a/api_docs/kbn_core_http_router_server_mocks.mdx +++ b/api_docs/kbn_core_http_router_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-router-server-mocks title: "@kbn/core-http-router-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-router-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-router-server-mocks'] --- import kbnCoreHttpRouterServerMocksObj from './kbn_core_http_router_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_http_server.devdocs.json b/api_docs/kbn_core_http_server.devdocs.json index 38e820536eba9..b2fdab00057fd 100644 --- a/api_docs/kbn_core_http_server.devdocs.json +++ b/api_docs/kbn_core_http_server.devdocs.json @@ -14514,6 +14514,10 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/management.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/get_attack_discovery.ts" + }, { "plugin": "elasticAssistant", "path": "x-pack/plugins/elastic_assistant/server/routes/user_conversations/read_route.ts" @@ -15281,6 +15285,10 @@ "plugin": "ml", "path": "x-pack/plugins/ml/server/routes/inference_models.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/cancel_attack_discovery.ts" + }, { "plugin": "elasticAssistant", "path": "x-pack/plugins/elastic_assistant/server/routes/user_conversations/update_route.ts" diff --git a/api_docs/kbn_core_http_server.mdx b/api_docs/kbn_core_http_server.mdx index 31a48995198eb..e8bcfe531bbbd 100644 --- a/api_docs/kbn_core_http_server.mdx +++ b/api_docs/kbn_core_http_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server title: "@kbn/core-http-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server'] --- import kbnCoreHttpServerObj from './kbn_core_http_server.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_internal.mdx b/api_docs/kbn_core_http_server_internal.mdx index 9dab9b6beba03..edb90e3d2eab9 100644 --- a/api_docs/kbn_core_http_server_internal.mdx +++ b/api_docs/kbn_core_http_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-internal title: "@kbn/core-http-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-internal'] --- import kbnCoreHttpServerInternalObj from './kbn_core_http_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_http_server_mocks.mdx b/api_docs/kbn_core_http_server_mocks.mdx index 6e060a4f4dc57..96a238c8ca13f 100644 --- a/api_docs/kbn_core_http_server_mocks.mdx +++ b/api_docs/kbn_core_http_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-http-server-mocks title: "@kbn/core-http-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-http-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-http-server-mocks'] --- import kbnCoreHttpServerMocksObj from './kbn_core_http_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser.mdx b/api_docs/kbn_core_i18n_browser.mdx index fc22c8a634e02..91f7b5d09831c 100644 --- a/api_docs/kbn_core_i18n_browser.mdx +++ b/api_docs/kbn_core_i18n_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser title: "@kbn/core-i18n-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser'] --- import kbnCoreI18nBrowserObj from './kbn_core_i18n_browser.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_browser_mocks.mdx b/api_docs/kbn_core_i18n_browser_mocks.mdx index d848a23a5c025..e4315933c86ff 100644 --- a/api_docs/kbn_core_i18n_browser_mocks.mdx +++ b/api_docs/kbn_core_i18n_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-browser-mocks title: "@kbn/core-i18n-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-browser-mocks'] --- import kbnCoreI18nBrowserMocksObj from './kbn_core_i18n_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server.mdx b/api_docs/kbn_core_i18n_server.mdx index 2a9d387070ff2..641f8a6dbcf7a 100644 --- a/api_docs/kbn_core_i18n_server.mdx +++ b/api_docs/kbn_core_i18n_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server title: "@kbn/core-i18n-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server'] --- import kbnCoreI18nServerObj from './kbn_core_i18n_server.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_internal.mdx b/api_docs/kbn_core_i18n_server_internal.mdx index bf17fe8ff97a3..d966fe364c5d7 100644 --- a/api_docs/kbn_core_i18n_server_internal.mdx +++ b/api_docs/kbn_core_i18n_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-internal title: "@kbn/core-i18n-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-internal'] --- import kbnCoreI18nServerInternalObj from './kbn_core_i18n_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_i18n_server_mocks.mdx b/api_docs/kbn_core_i18n_server_mocks.mdx index 9cc120b70f11f..2af026b8966a9 100644 --- a/api_docs/kbn_core_i18n_server_mocks.mdx +++ b/api_docs/kbn_core_i18n_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-i18n-server-mocks title: "@kbn/core-i18n-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-i18n-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-i18n-server-mocks'] --- import kbnCoreI18nServerMocksObj from './kbn_core_i18n_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx index 51619a29dd2e7..6a6703b366fb1 100644 --- a/api_docs/kbn_core_injected_metadata_browser_mocks.mdx +++ b/api_docs/kbn_core_injected_metadata_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-injected-metadata-browser-mocks title: "@kbn/core-injected-metadata-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-injected-metadata-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-injected-metadata-browser-mocks'] --- import kbnCoreInjectedMetadataBrowserMocksObj from './kbn_core_injected_metadata_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_internal.mdx b/api_docs/kbn_core_integrations_browser_internal.mdx index 465d0d447c28b..21eec775b8199 100644 --- a/api_docs/kbn_core_integrations_browser_internal.mdx +++ b/api_docs/kbn_core_integrations_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-internal title: "@kbn/core-integrations-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-internal'] --- import kbnCoreIntegrationsBrowserInternalObj from './kbn_core_integrations_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_integrations_browser_mocks.mdx b/api_docs/kbn_core_integrations_browser_mocks.mdx index 5aa661b011931..5c19c1069a4b3 100644 --- a/api_docs/kbn_core_integrations_browser_mocks.mdx +++ b/api_docs/kbn_core_integrations_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-integrations-browser-mocks title: "@kbn/core-integrations-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-integrations-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-integrations-browser-mocks'] --- import kbnCoreIntegrationsBrowserMocksObj from './kbn_core_integrations_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser.mdx b/api_docs/kbn_core_lifecycle_browser.mdx index 99a07974f69ff..25b397790fc72 100644 --- a/api_docs/kbn_core_lifecycle_browser.mdx +++ b/api_docs/kbn_core_lifecycle_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser title: "@kbn/core-lifecycle-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser'] --- import kbnCoreLifecycleBrowserObj from './kbn_core_lifecycle_browser.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_browser_mocks.mdx b/api_docs/kbn_core_lifecycle_browser_mocks.mdx index cc764e9f724e0..af2fe5ad1499a 100644 --- a/api_docs/kbn_core_lifecycle_browser_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-browser-mocks title: "@kbn/core-lifecycle-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-browser-mocks'] --- import kbnCoreLifecycleBrowserMocksObj from './kbn_core_lifecycle_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server.mdx b/api_docs/kbn_core_lifecycle_server.mdx index f6dee670906ff..ab2eb58bc359a 100644 --- a/api_docs/kbn_core_lifecycle_server.mdx +++ b/api_docs/kbn_core_lifecycle_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server title: "@kbn/core-lifecycle-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server'] --- import kbnCoreLifecycleServerObj from './kbn_core_lifecycle_server.devdocs.json'; diff --git a/api_docs/kbn_core_lifecycle_server_mocks.mdx b/api_docs/kbn_core_lifecycle_server_mocks.mdx index b0fba6644d175..1700ad7cecd11 100644 --- a/api_docs/kbn_core_lifecycle_server_mocks.mdx +++ b/api_docs/kbn_core_lifecycle_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-lifecycle-server-mocks title: "@kbn/core-lifecycle-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-lifecycle-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-lifecycle-server-mocks'] --- import kbnCoreLifecycleServerMocksObj from './kbn_core_lifecycle_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_browser_mocks.mdx b/api_docs/kbn_core_logging_browser_mocks.mdx index 3fdf110d65e77..0f9e84bb27adb 100644 --- a/api_docs/kbn_core_logging_browser_mocks.mdx +++ b/api_docs/kbn_core_logging_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-browser-mocks title: "@kbn/core-logging-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-browser-mocks'] --- import kbnCoreLoggingBrowserMocksObj from './kbn_core_logging_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_logging_common_internal.mdx b/api_docs/kbn_core_logging_common_internal.mdx index 8f0fd1cbd7385..cd6d9648ff76c 100644 --- a/api_docs/kbn_core_logging_common_internal.mdx +++ b/api_docs/kbn_core_logging_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-common-internal title: "@kbn/core-logging-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-common-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-common-internal'] --- import kbnCoreLoggingCommonInternalObj from './kbn_core_logging_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server.mdx b/api_docs/kbn_core_logging_server.mdx index 58e0f8daee792..73fb1d23f9287 100644 --- a/api_docs/kbn_core_logging_server.mdx +++ b/api_docs/kbn_core_logging_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server title: "@kbn/core-logging-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server'] --- import kbnCoreLoggingServerObj from './kbn_core_logging_server.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_internal.mdx b/api_docs/kbn_core_logging_server_internal.mdx index 795614105db1b..9e42cccb3e430 100644 --- a/api_docs/kbn_core_logging_server_internal.mdx +++ b/api_docs/kbn_core_logging_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-internal title: "@kbn/core-logging-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-internal'] --- import kbnCoreLoggingServerInternalObj from './kbn_core_logging_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_logging_server_mocks.mdx b/api_docs/kbn_core_logging_server_mocks.mdx index e51badc2b9787..a89c9f940e108 100644 --- a/api_docs/kbn_core_logging_server_mocks.mdx +++ b/api_docs/kbn_core_logging_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-logging-server-mocks title: "@kbn/core-logging-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-logging-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-logging-server-mocks'] --- import kbnCoreLoggingServerMocksObj from './kbn_core_logging_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_internal.mdx b/api_docs/kbn_core_metrics_collectors_server_internal.mdx index 59c9944ff359f..e87cb1281fae8 100644 --- a/api_docs/kbn_core_metrics_collectors_server_internal.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-internal title: "@kbn/core-metrics-collectors-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-internal'] --- import kbnCoreMetricsCollectorsServerInternalObj from './kbn_core_metrics_collectors_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx index a9d1bf5da2abc..100c6cf690663 100644 --- a/api_docs/kbn_core_metrics_collectors_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_collectors_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-collectors-server-mocks title: "@kbn/core-metrics-collectors-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-collectors-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-collectors-server-mocks'] --- import kbnCoreMetricsCollectorsServerMocksObj from './kbn_core_metrics_collectors_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server.mdx b/api_docs/kbn_core_metrics_server.mdx index 4df4607c93f53..e22beef47a058 100644 --- a/api_docs/kbn_core_metrics_server.mdx +++ b/api_docs/kbn_core_metrics_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server title: "@kbn/core-metrics-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server'] --- import kbnCoreMetricsServerObj from './kbn_core_metrics_server.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_internal.mdx b/api_docs/kbn_core_metrics_server_internal.mdx index 50e5400c11772..9d128ac242dd0 100644 --- a/api_docs/kbn_core_metrics_server_internal.mdx +++ b/api_docs/kbn_core_metrics_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-internal title: "@kbn/core-metrics-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-internal'] --- import kbnCoreMetricsServerInternalObj from './kbn_core_metrics_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_metrics_server_mocks.mdx b/api_docs/kbn_core_metrics_server_mocks.mdx index 6a676df5794bf..9a9bbd7bc0d22 100644 --- a/api_docs/kbn_core_metrics_server_mocks.mdx +++ b/api_docs/kbn_core_metrics_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-metrics-server-mocks title: "@kbn/core-metrics-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-metrics-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-metrics-server-mocks'] --- import kbnCoreMetricsServerMocksObj from './kbn_core_metrics_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_mount_utils_browser.mdx b/api_docs/kbn_core_mount_utils_browser.mdx index 9a5dfb4140991..098ad0d7208e7 100644 --- a/api_docs/kbn_core_mount_utils_browser.mdx +++ b/api_docs/kbn_core_mount_utils_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-mount-utils-browser title: "@kbn/core-mount-utils-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-mount-utils-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-mount-utils-browser'] --- import kbnCoreMountUtilsBrowserObj from './kbn_core_mount_utils_browser.devdocs.json'; diff --git a/api_docs/kbn_core_node_server.mdx b/api_docs/kbn_core_node_server.mdx index 89174827de71f..e629a23b67b61 100644 --- a/api_docs/kbn_core_node_server.mdx +++ b/api_docs/kbn_core_node_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server title: "@kbn/core-node-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server'] --- import kbnCoreNodeServerObj from './kbn_core_node_server.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_internal.mdx b/api_docs/kbn_core_node_server_internal.mdx index 39e41b72d7417..ecb30ace5794c 100644 --- a/api_docs/kbn_core_node_server_internal.mdx +++ b/api_docs/kbn_core_node_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-internal title: "@kbn/core-node-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-internal'] --- import kbnCoreNodeServerInternalObj from './kbn_core_node_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_node_server_mocks.mdx b/api_docs/kbn_core_node_server_mocks.mdx index 7b68311826dc6..9ea5a15b02a71 100644 --- a/api_docs/kbn_core_node_server_mocks.mdx +++ b/api_docs/kbn_core_node_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-node-server-mocks title: "@kbn/core-node-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-node-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-node-server-mocks'] --- import kbnCoreNodeServerMocksObj from './kbn_core_node_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser.mdx b/api_docs/kbn_core_notifications_browser.mdx index 4ca733b436629..e0b966079b556 100644 --- a/api_docs/kbn_core_notifications_browser.mdx +++ b/api_docs/kbn_core_notifications_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser title: "@kbn/core-notifications-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser'] --- import kbnCoreNotificationsBrowserObj from './kbn_core_notifications_browser.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_internal.mdx b/api_docs/kbn_core_notifications_browser_internal.mdx index d6f220c085655..50ea410f8c27e 100644 --- a/api_docs/kbn_core_notifications_browser_internal.mdx +++ b/api_docs/kbn_core_notifications_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-internal title: "@kbn/core-notifications-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-internal'] --- import kbnCoreNotificationsBrowserInternalObj from './kbn_core_notifications_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_notifications_browser_mocks.mdx b/api_docs/kbn_core_notifications_browser_mocks.mdx index ec35831d6fbee..d365149076f9a 100644 --- a/api_docs/kbn_core_notifications_browser_mocks.mdx +++ b/api_docs/kbn_core_notifications_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-notifications-browser-mocks title: "@kbn/core-notifications-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-notifications-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-notifications-browser-mocks'] --- import kbnCoreNotificationsBrowserMocksObj from './kbn_core_notifications_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser.mdx b/api_docs/kbn_core_overlays_browser.mdx index bf01ec19b49cc..e239cddb67f74 100644 --- a/api_docs/kbn_core_overlays_browser.mdx +++ b/api_docs/kbn_core_overlays_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser title: "@kbn/core-overlays-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser'] --- import kbnCoreOverlaysBrowserObj from './kbn_core_overlays_browser.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_internal.mdx b/api_docs/kbn_core_overlays_browser_internal.mdx index 259b37411158f..d72a29791ec0f 100644 --- a/api_docs/kbn_core_overlays_browser_internal.mdx +++ b/api_docs/kbn_core_overlays_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-internal title: "@kbn/core-overlays-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-internal'] --- import kbnCoreOverlaysBrowserInternalObj from './kbn_core_overlays_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_overlays_browser_mocks.mdx b/api_docs/kbn_core_overlays_browser_mocks.mdx index b2e11af835f81..9913224f315c9 100644 --- a/api_docs/kbn_core_overlays_browser_mocks.mdx +++ b/api_docs/kbn_core_overlays_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-overlays-browser-mocks title: "@kbn/core-overlays-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-overlays-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-overlays-browser-mocks'] --- import kbnCoreOverlaysBrowserMocksObj from './kbn_core_overlays_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser.mdx b/api_docs/kbn_core_plugins_browser.mdx index 879dc24b30258..3794fef8649e8 100644 --- a/api_docs/kbn_core_plugins_browser.mdx +++ b/api_docs/kbn_core_plugins_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser title: "@kbn/core-plugins-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser'] --- import kbnCorePluginsBrowserObj from './kbn_core_plugins_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_browser_mocks.mdx b/api_docs/kbn_core_plugins_browser_mocks.mdx index 4f5f1747b390e..00e4c03ba55e9 100644 --- a/api_docs/kbn_core_plugins_browser_mocks.mdx +++ b/api_docs/kbn_core_plugins_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-browser-mocks title: "@kbn/core-plugins-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-browser-mocks'] --- import kbnCorePluginsBrowserMocksObj from './kbn_core_plugins_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_browser.mdx b/api_docs/kbn_core_plugins_contracts_browser.mdx index b16efdbb7a4c2..75cbbbebd606e 100644 --- a/api_docs/kbn_core_plugins_contracts_browser.mdx +++ b/api_docs/kbn_core_plugins_contracts_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-browser title: "@kbn/core-plugins-contracts-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-browser'] --- import kbnCorePluginsContractsBrowserObj from './kbn_core_plugins_contracts_browser.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_contracts_server.mdx b/api_docs/kbn_core_plugins_contracts_server.mdx index 1cdd375e4e4ae..59fc4e4e8f17f 100644 --- a/api_docs/kbn_core_plugins_contracts_server.mdx +++ b/api_docs/kbn_core_plugins_contracts_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-contracts-server title: "@kbn/core-plugins-contracts-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-contracts-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-contracts-server'] --- import kbnCorePluginsContractsServerObj from './kbn_core_plugins_contracts_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server.mdx b/api_docs/kbn_core_plugins_server.mdx index edf2e1125d817..89735bfc1763a 100644 --- a/api_docs/kbn_core_plugins_server.mdx +++ b/api_docs/kbn_core_plugins_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server title: "@kbn/core-plugins-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server'] --- import kbnCorePluginsServerObj from './kbn_core_plugins_server.devdocs.json'; diff --git a/api_docs/kbn_core_plugins_server_mocks.mdx b/api_docs/kbn_core_plugins_server_mocks.mdx index 93d9e8b55c4f2..8c2ec99e3b6b3 100644 --- a/api_docs/kbn_core_plugins_server_mocks.mdx +++ b/api_docs/kbn_core_plugins_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-plugins-server-mocks title: "@kbn/core-plugins-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-plugins-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-plugins-server-mocks'] --- import kbnCorePluginsServerMocksObj from './kbn_core_plugins_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server.mdx b/api_docs/kbn_core_preboot_server.mdx index 02f635d008a10..fec5bf7e2ac16 100644 --- a/api_docs/kbn_core_preboot_server.mdx +++ b/api_docs/kbn_core_preboot_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server title: "@kbn/core-preboot-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server'] --- import kbnCorePrebootServerObj from './kbn_core_preboot_server.devdocs.json'; diff --git a/api_docs/kbn_core_preboot_server_mocks.mdx b/api_docs/kbn_core_preboot_server_mocks.mdx index 330d40aab5284..af0ae4a215d55 100644 --- a/api_docs/kbn_core_preboot_server_mocks.mdx +++ b/api_docs/kbn_core_preboot_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-preboot-server-mocks title: "@kbn/core-preboot-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-preboot-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-preboot-server-mocks'] --- import kbnCorePrebootServerMocksObj from './kbn_core_preboot_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_browser_mocks.mdx b/api_docs/kbn_core_rendering_browser_mocks.mdx index a937fa12b33db..ed63070af4d5c 100644 --- a/api_docs/kbn_core_rendering_browser_mocks.mdx +++ b/api_docs/kbn_core_rendering_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-browser-mocks title: "@kbn/core-rendering-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-browser-mocks'] --- import kbnCoreRenderingBrowserMocksObj from './kbn_core_rendering_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_internal.mdx b/api_docs/kbn_core_rendering_server_internal.mdx index 63e92bcc755bf..f6f3e0b6e327f 100644 --- a/api_docs/kbn_core_rendering_server_internal.mdx +++ b/api_docs/kbn_core_rendering_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-internal title: "@kbn/core-rendering-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-internal'] --- import kbnCoreRenderingServerInternalObj from './kbn_core_rendering_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_rendering_server_mocks.mdx b/api_docs/kbn_core_rendering_server_mocks.mdx index d69df5e81ba72..3773a9f836cc1 100644 --- a/api_docs/kbn_core_rendering_server_mocks.mdx +++ b/api_docs/kbn_core_rendering_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-rendering-server-mocks title: "@kbn/core-rendering-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-rendering-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-rendering-server-mocks'] --- import kbnCoreRenderingServerMocksObj from './kbn_core_rendering_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_root_server_internal.mdx b/api_docs/kbn_core_root_server_internal.mdx index 8e76e307c220d..5daeb13d9d6a9 100644 --- a/api_docs/kbn_core_root_server_internal.mdx +++ b/api_docs/kbn_core_root_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-root-server-internal title: "@kbn/core-root-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-root-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-root-server-internal'] --- import kbnCoreRootServerInternalObj from './kbn_core_root_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_browser.mdx b/api_docs/kbn_core_saved_objects_api_browser.mdx index 61897f6a82435..2ef188cb8d913 100644 --- a/api_docs/kbn_core_saved_objects_api_browser.mdx +++ b/api_docs/kbn_core_saved_objects_api_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-browser title: "@kbn/core-saved-objects-api-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-browser'] --- import kbnCoreSavedObjectsApiBrowserObj from './kbn_core_saved_objects_api_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server.mdx b/api_docs/kbn_core_saved_objects_api_server.mdx index f23a15b9c168f..272802ae63d70 100644 --- a/api_docs/kbn_core_saved_objects_api_server.mdx +++ b/api_docs/kbn_core_saved_objects_api_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server title: "@kbn/core-saved-objects-api-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server'] --- import kbnCoreSavedObjectsApiServerObj from './kbn_core_saved_objects_api_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx index 08493d6d5c890..bb608deacf562 100644 --- a/api_docs/kbn_core_saved_objects_api_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_api_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-api-server-mocks title: "@kbn/core-saved-objects-api-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-api-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-api-server-mocks'] --- import kbnCoreSavedObjectsApiServerMocksObj from './kbn_core_saved_objects_api_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_internal.mdx b/api_docs/kbn_core_saved_objects_base_server_internal.mdx index 52655e4129dec..7db8955b08c63 100644 --- a/api_docs/kbn_core_saved_objects_base_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-internal title: "@kbn/core-saved-objects-base-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-internal'] --- import kbnCoreSavedObjectsBaseServerInternalObj from './kbn_core_saved_objects_base_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx index 07cabbd809443..999313d3b0b2c 100644 --- a/api_docs/kbn_core_saved_objects_base_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_base_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-base-server-mocks title: "@kbn/core-saved-objects-base-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-base-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-base-server-mocks'] --- import kbnCoreSavedObjectsBaseServerMocksObj from './kbn_core_saved_objects_base_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser.mdx b/api_docs/kbn_core_saved_objects_browser.mdx index c8ff1e3c9695e..7a164a58215d5 100644 --- a/api_docs/kbn_core_saved_objects_browser.mdx +++ b/api_docs/kbn_core_saved_objects_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser title: "@kbn/core-saved-objects-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser'] --- import kbnCoreSavedObjectsBrowserObj from './kbn_core_saved_objects_browser.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_internal.mdx b/api_docs/kbn_core_saved_objects_browser_internal.mdx index 92dade7bc471a..3715a31dc06cd 100644 --- a/api_docs/kbn_core_saved_objects_browser_internal.mdx +++ b/api_docs/kbn_core_saved_objects_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-internal title: "@kbn/core-saved-objects-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-internal'] --- import kbnCoreSavedObjectsBrowserInternalObj from './kbn_core_saved_objects_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_browser_mocks.mdx b/api_docs/kbn_core_saved_objects_browser_mocks.mdx index e7dce3e4dd67e..7cf10ae0ba056 100644 --- a/api_docs/kbn_core_saved_objects_browser_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-browser-mocks title: "@kbn/core-saved-objects-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-browser-mocks'] --- import kbnCoreSavedObjectsBrowserMocksObj from './kbn_core_saved_objects_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_common.mdx b/api_docs/kbn_core_saved_objects_common.mdx index 637d11a4c7095..36348e6ce86e7 100644 --- a/api_docs/kbn_core_saved_objects_common.mdx +++ b/api_docs/kbn_core_saved_objects_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-common title: "@kbn/core-saved-objects-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-common'] --- import kbnCoreSavedObjectsCommonObj from './kbn_core_saved_objects_common.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx index 7bcbd57055f6f..fe7f1d9ae047d 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-internal title: "@kbn/core-saved-objects-import-export-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-internal'] --- import kbnCoreSavedObjectsImportExportServerInternalObj from './kbn_core_saved_objects_import_export_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx index 3aca9298b7ac9..141bdc82eb59e 100644 --- a/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_import_export_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-import-export-server-mocks title: "@kbn/core-saved-objects-import-export-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-import-export-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-import-export-server-mocks'] --- import kbnCoreSavedObjectsImportExportServerMocksObj from './kbn_core_saved_objects_import_export_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx index a7ed676987f72..b6e4b1d7f84c8 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-internal title: "@kbn/core-saved-objects-migration-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-internal'] --- import kbnCoreSavedObjectsMigrationServerInternalObj from './kbn_core_saved_objects_migration_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx index f06afc8e50195..e639673a5336e 100644 --- a/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_migration_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-migration-server-mocks title: "@kbn/core-saved-objects-migration-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-migration-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-migration-server-mocks'] --- import kbnCoreSavedObjectsMigrationServerMocksObj from './kbn_core_saved_objects_migration_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server.mdx b/api_docs/kbn_core_saved_objects_server.mdx index b0ba68b33d07e..136c9e6e27881 100644 --- a/api_docs/kbn_core_saved_objects_server.mdx +++ b/api_docs/kbn_core_saved_objects_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server title: "@kbn/core-saved-objects-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server'] --- import kbnCoreSavedObjectsServerObj from './kbn_core_saved_objects_server.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_internal.mdx b/api_docs/kbn_core_saved_objects_server_internal.mdx index 7430aba330175..44c78f74bcd84 100644 --- a/api_docs/kbn_core_saved_objects_server_internal.mdx +++ b/api_docs/kbn_core_saved_objects_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-internal title: "@kbn/core-saved-objects-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-internal'] --- import kbnCoreSavedObjectsServerInternalObj from './kbn_core_saved_objects_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_server_mocks.mdx b/api_docs/kbn_core_saved_objects_server_mocks.mdx index 273b7aa1a273d..4c69c2a3cead3 100644 --- a/api_docs/kbn_core_saved_objects_server_mocks.mdx +++ b/api_docs/kbn_core_saved_objects_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-server-mocks title: "@kbn/core-saved-objects-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-server-mocks'] --- import kbnCoreSavedObjectsServerMocksObj from './kbn_core_saved_objects_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_saved_objects_utils_server.mdx b/api_docs/kbn_core_saved_objects_utils_server.mdx index 6b588fd8f2537..60cc7895fedf4 100644 --- a/api_docs/kbn_core_saved_objects_utils_server.mdx +++ b/api_docs/kbn_core_saved_objects_utils_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-saved-objects-utils-server title: "@kbn/core-saved-objects-utils-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-saved-objects-utils-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-saved-objects-utils-server'] --- import kbnCoreSavedObjectsUtilsServerObj from './kbn_core_saved_objects_utils_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser.mdx b/api_docs/kbn_core_security_browser.mdx index 80299a1648897..f8a9b738b3de3 100644 --- a/api_docs/kbn_core_security_browser.mdx +++ b/api_docs/kbn_core_security_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser title: "@kbn/core-security-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser'] --- import kbnCoreSecurityBrowserObj from './kbn_core_security_browser.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_internal.mdx b/api_docs/kbn_core_security_browser_internal.mdx index ec2a5467d3875..d7aa4fc8c52dc 100644 --- a/api_docs/kbn_core_security_browser_internal.mdx +++ b/api_docs/kbn_core_security_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-internal title: "@kbn/core-security-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-internal'] --- import kbnCoreSecurityBrowserInternalObj from './kbn_core_security_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_browser_mocks.mdx b/api_docs/kbn_core_security_browser_mocks.mdx index 9d67d8aeb704b..fff414d122ff6 100644 --- a/api_docs/kbn_core_security_browser_mocks.mdx +++ b/api_docs/kbn_core_security_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-browser-mocks title: "@kbn/core-security-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-browser-mocks'] --- import kbnCoreSecurityBrowserMocksObj from './kbn_core_security_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_security_common.mdx b/api_docs/kbn_core_security_common.mdx index f71329052eabc..2e7fdf3ee37ae 100644 --- a/api_docs/kbn_core_security_common.mdx +++ b/api_docs/kbn_core_security_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-common title: "@kbn/core-security-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-common'] --- import kbnCoreSecurityCommonObj from './kbn_core_security_common.devdocs.json'; diff --git a/api_docs/kbn_core_security_server.mdx b/api_docs/kbn_core_security_server.mdx index 29d8d817aed66..627b4c07d6e25 100644 --- a/api_docs/kbn_core_security_server.mdx +++ b/api_docs/kbn_core_security_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server title: "@kbn/core-security-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server'] --- import kbnCoreSecurityServerObj from './kbn_core_security_server.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_internal.mdx b/api_docs/kbn_core_security_server_internal.mdx index fe650884ccc73..9da15d25adcab 100644 --- a/api_docs/kbn_core_security_server_internal.mdx +++ b/api_docs/kbn_core_security_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-internal title: "@kbn/core-security-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-internal'] --- import kbnCoreSecurityServerInternalObj from './kbn_core_security_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_security_server_mocks.mdx b/api_docs/kbn_core_security_server_mocks.mdx index 3dfd9ffb8c697..974f112aadc89 100644 --- a/api_docs/kbn_core_security_server_mocks.mdx +++ b/api_docs/kbn_core_security_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-security-server-mocks title: "@kbn/core-security-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-security-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-security-server-mocks'] --- import kbnCoreSecurityServerMocksObj from './kbn_core_security_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_status_common.mdx b/api_docs/kbn_core_status_common.mdx index c1e3e35ed5c51..08569be995c50 100644 --- a/api_docs/kbn_core_status_common.mdx +++ b/api_docs/kbn_core_status_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common title: "@kbn/core-status-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common'] --- import kbnCoreStatusCommonObj from './kbn_core_status_common.devdocs.json'; diff --git a/api_docs/kbn_core_status_common_internal.mdx b/api_docs/kbn_core_status_common_internal.mdx index 9ca6035f5b1a4..9c8804f9441d0 100644 --- a/api_docs/kbn_core_status_common_internal.mdx +++ b/api_docs/kbn_core_status_common_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-common-internal title: "@kbn/core-status-common-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-common-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-common-internal'] --- import kbnCoreStatusCommonInternalObj from './kbn_core_status_common_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server.mdx b/api_docs/kbn_core_status_server.mdx index 2e56b331aabad..582d307bfecf0 100644 --- a/api_docs/kbn_core_status_server.mdx +++ b/api_docs/kbn_core_status_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server title: "@kbn/core-status-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server'] --- import kbnCoreStatusServerObj from './kbn_core_status_server.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_internal.mdx b/api_docs/kbn_core_status_server_internal.mdx index 5c1ce43b01fc5..8ca9f5e75d4c5 100644 --- a/api_docs/kbn_core_status_server_internal.mdx +++ b/api_docs/kbn_core_status_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-internal title: "@kbn/core-status-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-internal'] --- import kbnCoreStatusServerInternalObj from './kbn_core_status_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_status_server_mocks.mdx b/api_docs/kbn_core_status_server_mocks.mdx index f9f1d91bdbcce..3233fa430a0cc 100644 --- a/api_docs/kbn_core_status_server_mocks.mdx +++ b/api_docs/kbn_core_status_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-status-server-mocks title: "@kbn/core-status-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-status-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-status-server-mocks'] --- import kbnCoreStatusServerMocksObj from './kbn_core_status_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx index a861f5fabce9e..e2cc70a015e1d 100644 --- a/api_docs/kbn_core_test_helpers_deprecations_getters.mdx +++ b/api_docs/kbn_core_test_helpers_deprecations_getters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-deprecations-getters title: "@kbn/core-test-helpers-deprecations-getters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-deprecations-getters plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-deprecations-getters'] --- import kbnCoreTestHelpersDeprecationsGettersObj from './kbn_core_test_helpers_deprecations_getters.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx index bb6b7e7197268..723c484e0cd22 100644 --- a/api_docs/kbn_core_test_helpers_http_setup_browser.mdx +++ b/api_docs/kbn_core_test_helpers_http_setup_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-http-setup-browser title: "@kbn/core-test-helpers-http-setup-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-http-setup-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-http-setup-browser'] --- import kbnCoreTestHelpersHttpSetupBrowserObj from './kbn_core_test_helpers_http_setup_browser.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_kbn_server.mdx b/api_docs/kbn_core_test_helpers_kbn_server.mdx index 0fd8f152bf039..7a81dcfc877d9 100644 --- a/api_docs/kbn_core_test_helpers_kbn_server.mdx +++ b/api_docs/kbn_core_test_helpers_kbn_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-kbn-server title: "@kbn/core-test-helpers-kbn-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-kbn-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-kbn-server'] --- import kbnCoreTestHelpersKbnServerObj from './kbn_core_test_helpers_kbn_server.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_model_versions.mdx b/api_docs/kbn_core_test_helpers_model_versions.mdx index 4e8fec23edc46..dd6dd635b082a 100644 --- a/api_docs/kbn_core_test_helpers_model_versions.mdx +++ b/api_docs/kbn_core_test_helpers_model_versions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-model-versions title: "@kbn/core-test-helpers-model-versions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-model-versions plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-model-versions'] --- import kbnCoreTestHelpersModelVersionsObj from './kbn_core_test_helpers_model_versions.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx index b2dfc63ca5ecc..42675573d0067 100644 --- a/api_docs/kbn_core_test_helpers_so_type_serializer.mdx +++ b/api_docs/kbn_core_test_helpers_so_type_serializer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-so-type-serializer title: "@kbn/core-test-helpers-so-type-serializer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-so-type-serializer plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-so-type-serializer'] --- import kbnCoreTestHelpersSoTypeSerializerObj from './kbn_core_test_helpers_so_type_serializer.devdocs.json'; diff --git a/api_docs/kbn_core_test_helpers_test_utils.mdx b/api_docs/kbn_core_test_helpers_test_utils.mdx index eab6bea5703fd..119ef703b386a 100644 --- a/api_docs/kbn_core_test_helpers_test_utils.mdx +++ b/api_docs/kbn_core_test_helpers_test_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-test-helpers-test-utils title: "@kbn/core-test-helpers-test-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-test-helpers-test-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-test-helpers-test-utils'] --- import kbnCoreTestHelpersTestUtilsObj from './kbn_core_test_helpers_test_utils.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser.mdx b/api_docs/kbn_core_theme_browser.mdx index 0c7f4f3783442..b76219d880058 100644 --- a/api_docs/kbn_core_theme_browser.mdx +++ b/api_docs/kbn_core_theme_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser title: "@kbn/core-theme-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser'] --- import kbnCoreThemeBrowserObj from './kbn_core_theme_browser.devdocs.json'; diff --git a/api_docs/kbn_core_theme_browser_mocks.mdx b/api_docs/kbn_core_theme_browser_mocks.mdx index d158d835d5000..ae2520fda748a 100644 --- a/api_docs/kbn_core_theme_browser_mocks.mdx +++ b/api_docs/kbn_core_theme_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-theme-browser-mocks title: "@kbn/core-theme-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-theme-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-theme-browser-mocks'] --- import kbnCoreThemeBrowserMocksObj from './kbn_core_theme_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser.mdx b/api_docs/kbn_core_ui_settings_browser.mdx index bf018d7119959..993907ce7371d 100644 --- a/api_docs/kbn_core_ui_settings_browser.mdx +++ b/api_docs/kbn_core_ui_settings_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser title: "@kbn/core-ui-settings-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser'] --- import kbnCoreUiSettingsBrowserObj from './kbn_core_ui_settings_browser.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_internal.mdx b/api_docs/kbn_core_ui_settings_browser_internal.mdx index 8a9565cbf402d..2654f768b20e9 100644 --- a/api_docs/kbn_core_ui_settings_browser_internal.mdx +++ b/api_docs/kbn_core_ui_settings_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-internal title: "@kbn/core-ui-settings-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-internal'] --- import kbnCoreUiSettingsBrowserInternalObj from './kbn_core_ui_settings_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_browser_mocks.mdx b/api_docs/kbn_core_ui_settings_browser_mocks.mdx index a0dfea50aab14..b47c2f9be181f 100644 --- a/api_docs/kbn_core_ui_settings_browser_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-browser-mocks title: "@kbn/core-ui-settings-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-browser-mocks'] --- import kbnCoreUiSettingsBrowserMocksObj from './kbn_core_ui_settings_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_common.mdx b/api_docs/kbn_core_ui_settings_common.mdx index d8065be548a1f..d2963a94cef48 100644 --- a/api_docs/kbn_core_ui_settings_common.mdx +++ b/api_docs/kbn_core_ui_settings_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-common title: "@kbn/core-ui-settings-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-common'] --- import kbnCoreUiSettingsCommonObj from './kbn_core_ui_settings_common.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server.mdx b/api_docs/kbn_core_ui_settings_server.mdx index f7bf40d00a067..2b74a5de4cb3b 100644 --- a/api_docs/kbn_core_ui_settings_server.mdx +++ b/api_docs/kbn_core_ui_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server title: "@kbn/core-ui-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server'] --- import kbnCoreUiSettingsServerObj from './kbn_core_ui_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_internal.mdx b/api_docs/kbn_core_ui_settings_server_internal.mdx index 5774087f48d89..81a8256c22605 100644 --- a/api_docs/kbn_core_ui_settings_server_internal.mdx +++ b/api_docs/kbn_core_ui_settings_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-internal title: "@kbn/core-ui-settings-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-internal'] --- import kbnCoreUiSettingsServerInternalObj from './kbn_core_ui_settings_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_ui_settings_server_mocks.mdx b/api_docs/kbn_core_ui_settings_server_mocks.mdx index 6ac2eed76db99..7bec683321740 100644 --- a/api_docs/kbn_core_ui_settings_server_mocks.mdx +++ b/api_docs/kbn_core_ui_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-ui-settings-server-mocks title: "@kbn/core-ui-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-ui-settings-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-ui-settings-server-mocks'] --- import kbnCoreUiSettingsServerMocksObj from './kbn_core_ui_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server.mdx b/api_docs/kbn_core_usage_data_server.mdx index 9fd3c275de806..f67d06b379c6f 100644 --- a/api_docs/kbn_core_usage_data_server.mdx +++ b/api_docs/kbn_core_usage_data_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server title: "@kbn/core-usage-data-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server'] --- import kbnCoreUsageDataServerObj from './kbn_core_usage_data_server.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_internal.mdx b/api_docs/kbn_core_usage_data_server_internal.mdx index 8e41e8ea04536..29360fc8a1711 100644 --- a/api_docs/kbn_core_usage_data_server_internal.mdx +++ b/api_docs/kbn_core_usage_data_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-internal title: "@kbn/core-usage-data-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-internal'] --- import kbnCoreUsageDataServerInternalObj from './kbn_core_usage_data_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_usage_data_server_mocks.mdx b/api_docs/kbn_core_usage_data_server_mocks.mdx index af611c80bb8f7..22e44607ff24b 100644 --- a/api_docs/kbn_core_usage_data_server_mocks.mdx +++ b/api_docs/kbn_core_usage_data_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-usage-data-server-mocks title: "@kbn/core-usage-data-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-usage-data-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-usage-data-server-mocks'] --- import kbnCoreUsageDataServerMocksObj from './kbn_core_usage_data_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser.mdx b/api_docs/kbn_core_user_profile_browser.mdx index e0f0fde32d1fe..63de05d139884 100644 --- a/api_docs/kbn_core_user_profile_browser.mdx +++ b/api_docs/kbn_core_user_profile_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser title: "@kbn/core-user-profile-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser'] --- import kbnCoreUserProfileBrowserObj from './kbn_core_user_profile_browser.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_internal.mdx b/api_docs/kbn_core_user_profile_browser_internal.mdx index 9a98d1310e006..ff6988716c6ef 100644 --- a/api_docs/kbn_core_user_profile_browser_internal.mdx +++ b/api_docs/kbn_core_user_profile_browser_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-internal title: "@kbn/core-user-profile-browser-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-internal'] --- import kbnCoreUserProfileBrowserInternalObj from './kbn_core_user_profile_browser_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_browser_mocks.mdx b/api_docs/kbn_core_user_profile_browser_mocks.mdx index 2c6c99fd12a6c..88c34eafafb76 100644 --- a/api_docs/kbn_core_user_profile_browser_mocks.mdx +++ b/api_docs/kbn_core_user_profile_browser_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-browser-mocks title: "@kbn/core-user-profile-browser-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-browser-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-browser-mocks'] --- import kbnCoreUserProfileBrowserMocksObj from './kbn_core_user_profile_browser_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_common.mdx b/api_docs/kbn_core_user_profile_common.mdx index 5b2bbeeb430be..233173f686b81 100644 --- a/api_docs/kbn_core_user_profile_common.mdx +++ b/api_docs/kbn_core_user_profile_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-common title: "@kbn/core-user-profile-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-common'] --- import kbnCoreUserProfileCommonObj from './kbn_core_user_profile_common.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server.mdx b/api_docs/kbn_core_user_profile_server.mdx index 368387abb0971..2d70d90ee9968 100644 --- a/api_docs/kbn_core_user_profile_server.mdx +++ b/api_docs/kbn_core_user_profile_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server title: "@kbn/core-user-profile-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server'] --- import kbnCoreUserProfileServerObj from './kbn_core_user_profile_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_internal.mdx b/api_docs/kbn_core_user_profile_server_internal.mdx index c9df40c14a6d0..ed3d1587c57c8 100644 --- a/api_docs/kbn_core_user_profile_server_internal.mdx +++ b/api_docs/kbn_core_user_profile_server_internal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-internal title: "@kbn/core-user-profile-server-internal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-internal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-internal'] --- import kbnCoreUserProfileServerInternalObj from './kbn_core_user_profile_server_internal.devdocs.json'; diff --git a/api_docs/kbn_core_user_profile_server_mocks.mdx b/api_docs/kbn_core_user_profile_server_mocks.mdx index 6fd0a6a46e8de..7fa716af3e261 100644 --- a/api_docs/kbn_core_user_profile_server_mocks.mdx +++ b/api_docs/kbn_core_user_profile_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-profile-server-mocks title: "@kbn/core-user-profile-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-profile-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-profile-server-mocks'] --- import kbnCoreUserProfileServerMocksObj from './kbn_core_user_profile_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server.mdx b/api_docs/kbn_core_user_settings_server.mdx index 9cd980b7ec274..04d77a8fca7f5 100644 --- a/api_docs/kbn_core_user_settings_server.mdx +++ b/api_docs/kbn_core_user_settings_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server title: "@kbn/core-user-settings-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server'] --- import kbnCoreUserSettingsServerObj from './kbn_core_user_settings_server.devdocs.json'; diff --git a/api_docs/kbn_core_user_settings_server_mocks.mdx b/api_docs/kbn_core_user_settings_server_mocks.mdx index a5ac572bb3ce1..7216c172cd9ba 100644 --- a/api_docs/kbn_core_user_settings_server_mocks.mdx +++ b/api_docs/kbn_core_user_settings_server_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-core-user-settings-server-mocks title: "@kbn/core-user-settings-server-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/core-user-settings-server-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/core-user-settings-server-mocks'] --- import kbnCoreUserSettingsServerMocksObj from './kbn_core_user_settings_server_mocks.devdocs.json'; diff --git a/api_docs/kbn_crypto.mdx b/api_docs/kbn_crypto.mdx index 5b043729102cd..6d101ba0330bd 100644 --- a/api_docs/kbn_crypto.mdx +++ b/api_docs/kbn_crypto.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto title: "@kbn/crypto" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto'] --- import kbnCryptoObj from './kbn_crypto.devdocs.json'; diff --git a/api_docs/kbn_crypto_browser.mdx b/api_docs/kbn_crypto_browser.mdx index 70c2e56b45331..ce5434e07da39 100644 --- a/api_docs/kbn_crypto_browser.mdx +++ b/api_docs/kbn_crypto_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-crypto-browser title: "@kbn/crypto-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/crypto-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/crypto-browser'] --- import kbnCryptoBrowserObj from './kbn_crypto_browser.devdocs.json'; diff --git a/api_docs/kbn_custom_icons.mdx b/api_docs/kbn_custom_icons.mdx index f305f06a7f5f7..26efcd119a86d 100644 --- a/api_docs/kbn_custom_icons.mdx +++ b/api_docs/kbn_custom_icons.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-icons title: "@kbn/custom-icons" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-icons plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-icons'] --- import kbnCustomIconsObj from './kbn_custom_icons.devdocs.json'; diff --git a/api_docs/kbn_custom_integrations.mdx b/api_docs/kbn_custom_integrations.mdx index 3d6fca2a0f50b..1947d3be29383 100644 --- a/api_docs/kbn_custom_integrations.mdx +++ b/api_docs/kbn_custom_integrations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-custom-integrations title: "@kbn/custom-integrations" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/custom-integrations plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/custom-integrations'] --- import kbnCustomIntegrationsObj from './kbn_custom_integrations.devdocs.json'; diff --git a/api_docs/kbn_cypress_config.mdx b/api_docs/kbn_cypress_config.mdx index d5ab7a2846f4c..1b03fb8e8d19b 100644 --- a/api_docs/kbn_cypress_config.mdx +++ b/api_docs/kbn_cypress_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-cypress-config title: "@kbn/cypress-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/cypress-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/cypress-config'] --- import kbnCypressConfigObj from './kbn_cypress_config.devdocs.json'; diff --git a/api_docs/kbn_data_forge.mdx b/api_docs/kbn_data_forge.mdx index cf3ba7d267e1e..b844a916fcd09 100644 --- a/api_docs/kbn_data_forge.mdx +++ b/api_docs/kbn_data_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-forge title: "@kbn/data-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-forge plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-forge'] --- import kbnDataForgeObj from './kbn_data_forge.devdocs.json'; diff --git a/api_docs/kbn_data_service.mdx b/api_docs/kbn_data_service.mdx index 1b1025f1288b2..000a58945eae4 100644 --- a/api_docs/kbn_data_service.mdx +++ b/api_docs/kbn_data_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-service title: "@kbn/data-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-service plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-service'] --- import kbnDataServiceObj from './kbn_data_service.devdocs.json'; diff --git a/api_docs/kbn_data_stream_adapter.mdx b/api_docs/kbn_data_stream_adapter.mdx index c71a7749df581..0e9c7df7f9b89 100644 --- a/api_docs/kbn_data_stream_adapter.mdx +++ b/api_docs/kbn_data_stream_adapter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-stream-adapter title: "@kbn/data-stream-adapter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-stream-adapter plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-stream-adapter'] --- import kbnDataStreamAdapterObj from './kbn_data_stream_adapter.devdocs.json'; diff --git a/api_docs/kbn_data_view_utils.mdx b/api_docs/kbn_data_view_utils.mdx index 61a5d34112b31..61c574f94fb5f 100644 --- a/api_docs/kbn_data_view_utils.mdx +++ b/api_docs/kbn_data_view_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-data-view-utils title: "@kbn/data-view-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/data-view-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/data-view-utils'] --- import kbnDataViewUtilsObj from './kbn_data_view_utils.devdocs.json'; diff --git a/api_docs/kbn_datemath.mdx b/api_docs/kbn_datemath.mdx index 7aa016375fb1c..db7c839f0e5c5 100644 --- a/api_docs/kbn_datemath.mdx +++ b/api_docs/kbn_datemath.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-datemath title: "@kbn/datemath" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/datemath plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/datemath'] --- import kbnDatemathObj from './kbn_datemath.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_analytics.mdx b/api_docs/kbn_deeplinks_analytics.mdx index 796c594c32203..16bdbfe2b20a5 100644 --- a/api_docs/kbn_deeplinks_analytics.mdx +++ b/api_docs/kbn_deeplinks_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-analytics title: "@kbn/deeplinks-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-analytics plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-analytics'] --- import kbnDeeplinksAnalyticsObj from './kbn_deeplinks_analytics.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_devtools.mdx b/api_docs/kbn_deeplinks_devtools.mdx index 3289697059fd0..568da8477941d 100644 --- a/api_docs/kbn_deeplinks_devtools.mdx +++ b/api_docs/kbn_deeplinks_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-devtools title: "@kbn/deeplinks-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-devtools plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-devtools'] --- import kbnDeeplinksDevtoolsObj from './kbn_deeplinks_devtools.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_fleet.mdx b/api_docs/kbn_deeplinks_fleet.mdx index 042a19a477777..898127d1cafc3 100644 --- a/api_docs/kbn_deeplinks_fleet.mdx +++ b/api_docs/kbn_deeplinks_fleet.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-fleet title: "@kbn/deeplinks-fleet" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-fleet plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-fleet'] --- import kbnDeeplinksFleetObj from './kbn_deeplinks_fleet.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_management.mdx b/api_docs/kbn_deeplinks_management.mdx index e0123aa5f15a5..5bddf7fc0d9a8 100644 --- a/api_docs/kbn_deeplinks_management.mdx +++ b/api_docs/kbn_deeplinks_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-management title: "@kbn/deeplinks-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-management plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-management'] --- import kbnDeeplinksManagementObj from './kbn_deeplinks_management.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_ml.mdx b/api_docs/kbn_deeplinks_ml.mdx index 66ea5c066c036..3f0053324dcce 100644 --- a/api_docs/kbn_deeplinks_ml.mdx +++ b/api_docs/kbn_deeplinks_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-ml title: "@kbn/deeplinks-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-ml plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-ml'] --- import kbnDeeplinksMlObj from './kbn_deeplinks_ml.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_observability.mdx b/api_docs/kbn_deeplinks_observability.mdx index 93fde0ca5fb8d..5fae9c44f400e 100644 --- a/api_docs/kbn_deeplinks_observability.mdx +++ b/api_docs/kbn_deeplinks_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-observability title: "@kbn/deeplinks-observability" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-observability plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-observability'] --- import kbnDeeplinksObservabilityObj from './kbn_deeplinks_observability.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_search.mdx b/api_docs/kbn_deeplinks_search.mdx index 019c5e147acf7..a06c09443692f 100644 --- a/api_docs/kbn_deeplinks_search.mdx +++ b/api_docs/kbn_deeplinks_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-search title: "@kbn/deeplinks-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-search plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-search'] --- import kbnDeeplinksSearchObj from './kbn_deeplinks_search.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_security.mdx b/api_docs/kbn_deeplinks_security.mdx index d733af699fb1f..5eca1ae3764b8 100644 --- a/api_docs/kbn_deeplinks_security.mdx +++ b/api_docs/kbn_deeplinks_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-security title: "@kbn/deeplinks-security" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-security plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-security'] --- import kbnDeeplinksSecurityObj from './kbn_deeplinks_security.devdocs.json'; diff --git a/api_docs/kbn_deeplinks_shared.mdx b/api_docs/kbn_deeplinks_shared.mdx index 954a8c816bea9..e2b38484d2c79 100644 --- a/api_docs/kbn_deeplinks_shared.mdx +++ b/api_docs/kbn_deeplinks_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-deeplinks-shared title: "@kbn/deeplinks-shared" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/deeplinks-shared plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/deeplinks-shared'] --- import kbnDeeplinksSharedObj from './kbn_deeplinks_shared.devdocs.json'; diff --git a/api_docs/kbn_default_nav_analytics.mdx b/api_docs/kbn_default_nav_analytics.mdx index aeb8706e3ff46..db2ebc1631fd3 100644 --- a/api_docs/kbn_default_nav_analytics.mdx +++ b/api_docs/kbn_default_nav_analytics.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-analytics title: "@kbn/default-nav-analytics" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-analytics plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-analytics'] --- import kbnDefaultNavAnalyticsObj from './kbn_default_nav_analytics.devdocs.json'; diff --git a/api_docs/kbn_default_nav_devtools.mdx b/api_docs/kbn_default_nav_devtools.mdx index 15bd6c86b1d7e..94435a5c00514 100644 --- a/api_docs/kbn_default_nav_devtools.mdx +++ b/api_docs/kbn_default_nav_devtools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-devtools title: "@kbn/default-nav-devtools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-devtools plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-devtools'] --- import kbnDefaultNavDevtoolsObj from './kbn_default_nav_devtools.devdocs.json'; diff --git a/api_docs/kbn_default_nav_management.mdx b/api_docs/kbn_default_nav_management.mdx index d29a95aefc6a6..6883eae8510c5 100644 --- a/api_docs/kbn_default_nav_management.mdx +++ b/api_docs/kbn_default_nav_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-management title: "@kbn/default-nav-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-management plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-management'] --- import kbnDefaultNavManagementObj from './kbn_default_nav_management.devdocs.json'; diff --git a/api_docs/kbn_default_nav_ml.mdx b/api_docs/kbn_default_nav_ml.mdx index 949b9ba9325bd..98c923207a8cc 100644 --- a/api_docs/kbn_default_nav_ml.mdx +++ b/api_docs/kbn_default_nav_ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-default-nav-ml title: "@kbn/default-nav-ml" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/default-nav-ml plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/default-nav-ml'] --- import kbnDefaultNavMlObj from './kbn_default_nav_ml.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_errors.mdx b/api_docs/kbn_dev_cli_errors.mdx index 2398a43ec7fc4..bc961d75a43e4 100644 --- a/api_docs/kbn_dev_cli_errors.mdx +++ b/api_docs/kbn_dev_cli_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-errors title: "@kbn/dev-cli-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-errors plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-errors'] --- import kbnDevCliErrorsObj from './kbn_dev_cli_errors.devdocs.json'; diff --git a/api_docs/kbn_dev_cli_runner.mdx b/api_docs/kbn_dev_cli_runner.mdx index f284fd4497f62..4d5887fc232ca 100644 --- a/api_docs/kbn_dev_cli_runner.mdx +++ b/api_docs/kbn_dev_cli_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-cli-runner title: "@kbn/dev-cli-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-cli-runner plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-cli-runner'] --- import kbnDevCliRunnerObj from './kbn_dev_cli_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_proc_runner.mdx b/api_docs/kbn_dev_proc_runner.mdx index cf95aae082bee..c4ec82547cf7a 100644 --- a/api_docs/kbn_dev_proc_runner.mdx +++ b/api_docs/kbn_dev_proc_runner.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-proc-runner title: "@kbn/dev-proc-runner" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-proc-runner plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-proc-runner'] --- import kbnDevProcRunnerObj from './kbn_dev_proc_runner.devdocs.json'; diff --git a/api_docs/kbn_dev_utils.mdx b/api_docs/kbn_dev_utils.mdx index 9c02c01cba875..e9f2d27397999 100644 --- a/api_docs/kbn_dev_utils.mdx +++ b/api_docs/kbn_dev_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dev-utils title: "@kbn/dev-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dev-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dev-utils'] --- import kbnDevUtilsObj from './kbn_dev_utils.devdocs.json'; diff --git a/api_docs/kbn_discover_utils.mdx b/api_docs/kbn_discover_utils.mdx index 6457526831824..a57b6049750f3 100644 --- a/api_docs/kbn_discover_utils.mdx +++ b/api_docs/kbn_discover_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-discover-utils title: "@kbn/discover-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/discover-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/discover-utils'] --- import kbnDiscoverUtilsObj from './kbn_discover_utils.devdocs.json'; diff --git a/api_docs/kbn_doc_links.mdx b/api_docs/kbn_doc_links.mdx index a8055499813e0..9ba1f68e6a89d 100644 --- a/api_docs/kbn_doc_links.mdx +++ b/api_docs/kbn_doc_links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-doc-links title: "@kbn/doc-links" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/doc-links plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/doc-links'] --- import kbnDocLinksObj from './kbn_doc_links.devdocs.json'; diff --git a/api_docs/kbn_docs_utils.mdx b/api_docs/kbn_docs_utils.mdx index 67c3a80c9cfec..b49fb8a59df80 100644 --- a/api_docs/kbn_docs_utils.mdx +++ b/api_docs/kbn_docs_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-docs-utils title: "@kbn/docs-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/docs-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/docs-utils'] --- import kbnDocsUtilsObj from './kbn_docs_utils.devdocs.json'; diff --git a/api_docs/kbn_dom_drag_drop.mdx b/api_docs/kbn_dom_drag_drop.mdx index abfd5d93a2726..f0b93301823b9 100644 --- a/api_docs/kbn_dom_drag_drop.mdx +++ b/api_docs/kbn_dom_drag_drop.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-dom-drag-drop title: "@kbn/dom-drag-drop" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/dom-drag-drop plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/dom-drag-drop'] --- import kbnDomDragDropObj from './kbn_dom_drag_drop.devdocs.json'; diff --git a/api_docs/kbn_ebt.devdocs.json b/api_docs/kbn_ebt.devdocs.json index 82e6770af4fac..82e5dbb2ad965 100644 --- a/api_docs/kbn_ebt.devdocs.json +++ b/api_docs/kbn_ebt.devdocs.json @@ -1866,6 +1866,22 @@ "plugin": "elasticAssistant", "path": "x-pack/plugins/elastic_assistant/server/lib/langchain/elasticsearch_store/elasticsearch_store.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.ts" + }, { "plugin": "globalSearchBar", "path": "x-pack/plugins/global_search_bar/public/telemetry/event_reporter.ts" @@ -2042,10 +2058,6 @@ "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" }, - { - "plugin": "securitySolution", - "path": "x-pack/plugins/security_solution/public/common/lib/telemetry/telemetry_client.ts" - }, { "plugin": "securitySolution", "path": "x-pack/plugins/security_solution/server/lib/entity_analytics/asset_criticality/routes/upload_csv.ts" @@ -2174,6 +2186,38 @@ "plugin": "security", "path": "x-pack/plugins/security/server/analytics/analytics_service.test.ts" }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, + { + "plugin": "elasticAssistant", + "path": "x-pack/plugins/elastic_assistant/server/routes/attack_discovery/helpers.test.ts" + }, { "plugin": "apm", "path": "x-pack/plugins/observability_solution/apm/public/services/telemetry/telemetry_service.test.ts" diff --git a/api_docs/kbn_ebt.mdx b/api_docs/kbn_ebt.mdx index ab81064b8ea53..7297cb9ea03f8 100644 --- a/api_docs/kbn_ebt.mdx +++ b/api_docs/kbn_ebt.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt title: "@kbn/ebt" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt'] --- import kbnEbtObj from './kbn_ebt.devdocs.json'; diff --git a/api_docs/kbn_ebt_tools.mdx b/api_docs/kbn_ebt_tools.mdx index 85345fe802729..1bf7dc9f60c01 100644 --- a/api_docs/kbn_ebt_tools.mdx +++ b/api_docs/kbn_ebt_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ebt-tools title: "@kbn/ebt-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ebt-tools plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ebt-tools'] --- import kbnEbtToolsObj from './kbn_ebt_tools.devdocs.json'; diff --git a/api_docs/kbn_ecs_data_quality_dashboard.mdx b/api_docs/kbn_ecs_data_quality_dashboard.mdx index 6866cbef051b3..a9a87c80a7f73 100644 --- a/api_docs/kbn_ecs_data_quality_dashboard.mdx +++ b/api_docs/kbn_ecs_data_quality_dashboard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ecs-data-quality-dashboard title: "@kbn/ecs-data-quality-dashboard" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ecs-data-quality-dashboard plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ecs-data-quality-dashboard'] --- import kbnEcsDataQualityDashboardObj from './kbn_ecs_data_quality_dashboard.devdocs.json'; diff --git a/api_docs/kbn_elastic_agent_utils.mdx b/api_docs/kbn_elastic_agent_utils.mdx index 0b17030083bfc..baf196e416949 100644 --- a/api_docs/kbn_elastic_agent_utils.mdx +++ b/api_docs/kbn_elastic_agent_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-agent-utils title: "@kbn/elastic-agent-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-agent-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-agent-utils'] --- import kbnElasticAgentUtilsObj from './kbn_elastic_agent_utils.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant.mdx b/api_docs/kbn_elastic_assistant.mdx index d83f3905e6a32..ad273ccd01b94 100644 --- a/api_docs/kbn_elastic_assistant.mdx +++ b/api_docs/kbn_elastic_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant title: "@kbn/elastic-assistant" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant'] --- import kbnElasticAssistantObj from './kbn_elastic_assistant.devdocs.json'; diff --git a/api_docs/kbn_elastic_assistant_common.devdocs.json b/api_docs/kbn_elastic_assistant_common.devdocs.json index 7f5b1cccc8780..2e245eee05c74 100644 --- a/api_docs/kbn_elastic_assistant_common.devdocs.json +++ b/api_docs/kbn_elastic_assistant_common.devdocs.json @@ -851,6 +851,23 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveries", + "type": "Type", + "tags": [], + "label": "AttackDiscoveries", + "description": [ + "\nArray of attack discoveries" + ], + "signature": [ + "{ timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.AttackDiscovery", @@ -861,9 +878,114 @@ "\nAn attack discovery generated from one or more alerts" ], "signature": [ - "{ title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; mitreAttackTactics?: string[] | undefined; }" + "{ timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }" ], - "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts", + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryCancelRequestParams", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryCancelRequestParams", + "description": [], + "signature": [ + "{ connectorId: string; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryCancelRequestParamsInput", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryCancelRequestParamsInput", + "description": [], + "signature": [ + "{ connectorId: string; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryCancelResponse", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryCancelResponse", + "description": [], + "signature": [ + "{ id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryCreateProps", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryCreateProps", + "description": [], + "signature": [ + "{ status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; id?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryGetRequestParams", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryGetRequestParams", + "description": [], + "signature": [ + "{ connectorId: string; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryGetRequestParamsInput", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryGetRequestParamsInput", + "description": [], + "signature": [ + "{ connectorId: string; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryGetResponse", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryGetResponse", + "description": [], + "signature": [ + "{ entryExists: boolean; data?: { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; } | undefined; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -876,7 +998,7 @@ "label": "AttackDiscoveryPostRequestBody", "description": [], "signature": [ - "{ connectorId: string; actionTypeId: string; size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; }" + "{ size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; }" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts", "deprecated": false, @@ -891,7 +1013,7 @@ "label": "AttackDiscoveryPostRequestBodyInput", "description": [], "signature": [ - "{ connectorId: string; actionTypeId: string; size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; }" + "{ size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; }" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts", "deprecated": false, @@ -906,13 +1028,75 @@ "label": "AttackDiscoveryPostResponse", "description": [], "signature": [ - "{ connector_id?: string | undefined; alertsContextCount?: number | undefined; attackDiscoveries?: { title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; mitreAttackTactics?: string[] | undefined; }[] | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; status?: string | undefined; trace_data?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }" + "{ id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryResponse", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryResponse", + "description": [], + "signature": [ + "{ id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryStatus", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryStatus", + "description": [ + "\nThe status of the attack discovery." + ], + "signature": [ + "\"running\" | \"succeeded\" | \"failed\" | \"canceled\"" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryStatusEnum", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryStatusEnum", + "description": [], + "signature": [ + "{ running: \"running\"; succeeded: \"succeeded\"; failed: \"failed\"; canceled: \"canceled\"; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryUpdateProps", + "type": "Type", + "tags": [], + "label": "AttackDiscoveryUpdateProps", + "description": [], + "signature": [ + "{ id: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; backingIndex: string; apiConfig?: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; } | undefined; alertsContextCount?: number | undefined; attackDiscoveries?: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[] | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; generationIntervals?: { date: string; durationMs: number; }[] | undefined; failureReason?: string | undefined; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.BulkActionBase", @@ -1967,6 +2151,23 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.GenerationInterval", + "type": "Type", + "tags": [], + "label": "GenerationInterval", + "description": [ + "\nRun durations for the attack discovery" + ], + "signature": [ + "{ date: string; durationMs: number; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.GetCapabilitiesResponse", @@ -3088,6 +3289,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveries", + "type": "Object", + "tags": [], + "label": "AttackDiscoveries", + "description": [], + "signature": [ + "Zod.ZodArray<Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; id: Zod.ZodOptional<Zod.ZodString>; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; timestamp: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }>, \"many\">" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.AttackDiscovery", @@ -3096,9 +3312,84 @@ "label": "AttackDiscovery", "description": [], "signature": [ - "Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; mitreAttackTactics?: string[] | undefined; }, { title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; mitreAttackTactics?: string[] | undefined; }>" + "Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; id: Zod.ZodOptional<Zod.ZodString>; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; timestamp: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }>" ], - "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts", + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryCancelRequestParams", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryCancelRequestParams", + "description": [], + "signature": [ + "Zod.ZodObject<{ connectorId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; }, { connectorId: string; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryCancelResponse", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryCancelResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ id: Zod.ZodString; timestamp: Zod.ZodOptional<Zod.ZodString>; updatedAt: Zod.ZodOptional<Zod.ZodString>; alertsContextCount: Zod.ZodOptional<Zod.ZodNumber>; createdAt: Zod.ZodString; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; users: Zod.ZodArray<Zod.ZodObject<{ id: Zod.ZodOptional<Zod.ZodString>; name: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id?: string | undefined; name?: string | undefined; }, { id?: string | undefined; name?: string | undefined; }>, \"many\">; status: Zod.ZodEnum<[\"running\", \"succeeded\", \"failed\", \"canceled\"]>; attackDiscoveries: Zod.ZodArray<Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; id: Zod.ZodOptional<Zod.ZodString>; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; timestamp: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }>, \"many\">; apiConfig: Zod.ZodObject<{ connectorId: Zod.ZodString; actionTypeId: Zod.ZodString; defaultSystemPromptId: Zod.ZodOptional<Zod.ZodString>; provider: Zod.ZodOptional<Zod.ZodEnum<[\"OpenAI\", \"Azure OpenAI\"]>>; model: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }>; namespace: Zod.ZodString; backingIndex: Zod.ZodString; generationIntervals: Zod.ZodArray<Zod.ZodObject<{ date: Zod.ZodString; durationMs: Zod.ZodNumber; }, \"strip\", Zod.ZodTypeAny, { date: string; durationMs: number; }, { date: string; durationMs: number; }>, \"many\">; averageIntervalMs: Zod.ZodNumber; failureReason: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }, { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/cancel_attack_discovery_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryCreateProps", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryCreateProps", + "description": [], + "signature": [ + "Zod.ZodObject<{ id: Zod.ZodOptional<Zod.ZodString>; status: Zod.ZodEnum<[\"running\", \"succeeded\", \"failed\", \"canceled\"]>; alertsContextCount: Zod.ZodOptional<Zod.ZodNumber>; attackDiscoveries: Zod.ZodArray<Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; id: Zod.ZodOptional<Zod.ZodString>; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; timestamp: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }>, \"many\">; apiConfig: Zod.ZodObject<{ connectorId: Zod.ZodString; actionTypeId: Zod.ZodString; defaultSystemPromptId: Zod.ZodOptional<Zod.ZodString>; provider: Zod.ZodOptional<Zod.ZodEnum<[\"OpenAI\", \"Azure OpenAI\"]>>; model: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }>; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; }, \"strip\", Zod.ZodTypeAny, { status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; id?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; }, { status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; id?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryGetRequestParams", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryGetRequestParams", + "description": [], + "signature": [ + "Zod.ZodObject<{ connectorId: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; }, { connectorId: string; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryGetResponse", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryGetResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ data: Zod.ZodOptional<Zod.ZodObject<{ id: Zod.ZodString; timestamp: Zod.ZodOptional<Zod.ZodString>; updatedAt: Zod.ZodOptional<Zod.ZodString>; alertsContextCount: Zod.ZodOptional<Zod.ZodNumber>; createdAt: Zod.ZodString; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; users: Zod.ZodArray<Zod.ZodObject<{ id: Zod.ZodOptional<Zod.ZodString>; name: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id?: string | undefined; name?: string | undefined; }, { id?: string | undefined; name?: string | undefined; }>, \"many\">; status: Zod.ZodEnum<[\"running\", \"succeeded\", \"failed\", \"canceled\"]>; attackDiscoveries: Zod.ZodArray<Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; id: Zod.ZodOptional<Zod.ZodString>; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; timestamp: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }>, \"many\">; apiConfig: Zod.ZodObject<{ connectorId: Zod.ZodString; actionTypeId: Zod.ZodString; defaultSystemPromptId: Zod.ZodOptional<Zod.ZodString>; provider: Zod.ZodOptional<Zod.ZodEnum<[\"OpenAI\", \"Azure OpenAI\"]>>; model: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }>; namespace: Zod.ZodString; backingIndex: Zod.ZodString; generationIntervals: Zod.ZodArray<Zod.ZodObject<{ date: Zod.ZodString; durationMs: Zod.ZodNumber; }, \"strip\", Zod.ZodTypeAny, { date: string; durationMs: number; }, { date: string; durationMs: number; }>, \"many\">; averageIntervalMs: Zod.ZodNumber; failureReason: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }, { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }>>; entryExists: Zod.ZodBoolean; }, \"strip\", Zod.ZodTypeAny, { entryExists: boolean; data?: { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; } | undefined; }, { entryExists: boolean; data?: { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; } | undefined; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/get_attack_discovery_route.gen.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false @@ -3111,7 +3402,7 @@ "label": "AttackDiscoveryPostRequestBody", "description": [], "signature": [ - "Zod.ZodObject<{ alertsIndexPattern: Zod.ZodString; anonymizationFields: Zod.ZodArray<Zod.ZodObject<{ id: Zod.ZodString; timestamp: Zod.ZodOptional<Zod.ZodString>; field: Zod.ZodString; allowed: Zod.ZodOptional<Zod.ZodBoolean>; anonymized: Zod.ZodOptional<Zod.ZodBoolean>; updatedAt: Zod.ZodOptional<Zod.ZodString>; updatedBy: Zod.ZodOptional<Zod.ZodString>; createdAt: Zod.ZodOptional<Zod.ZodString>; createdBy: Zod.ZodOptional<Zod.ZodString>; namespace: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }, { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }>, \"many\">; connectorId: Zod.ZodString; actionTypeId: Zod.ZodString; langSmithProject: Zod.ZodOptional<Zod.ZodString>; langSmithApiKey: Zod.ZodOptional<Zod.ZodString>; model: Zod.ZodOptional<Zod.ZodString>; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; size: Zod.ZodNumber; subAction: Zod.ZodEnum<[\"invokeAI\", \"invokeStream\"]>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; }, { connectorId: string; actionTypeId: string; size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; }>" + "Zod.ZodObject<{ alertsIndexPattern: Zod.ZodString; anonymizationFields: Zod.ZodArray<Zod.ZodObject<{ id: Zod.ZodString; timestamp: Zod.ZodOptional<Zod.ZodString>; field: Zod.ZodString; allowed: Zod.ZodOptional<Zod.ZodBoolean>; anonymized: Zod.ZodOptional<Zod.ZodBoolean>; updatedAt: Zod.ZodOptional<Zod.ZodString>; updatedBy: Zod.ZodOptional<Zod.ZodString>; createdAt: Zod.ZodOptional<Zod.ZodString>; createdBy: Zod.ZodOptional<Zod.ZodString>; namespace: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }, { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }>, \"many\">; apiConfig: Zod.ZodObject<{ connectorId: Zod.ZodString; actionTypeId: Zod.ZodString; defaultSystemPromptId: Zod.ZodOptional<Zod.ZodString>; provider: Zod.ZodOptional<Zod.ZodEnum<[\"OpenAI\", \"Azure OpenAI\"]>>; model: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }>; langSmithProject: Zod.ZodOptional<Zod.ZodString>; langSmithApiKey: Zod.ZodOptional<Zod.ZodString>; model: Zod.ZodOptional<Zod.ZodString>; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; size: Zod.ZodNumber; subAction: Zod.ZodEnum<[\"invokeAI\", \"invokeStream\"]>; }, \"strip\", Zod.ZodTypeAny, { size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; }, { size: number; subAction: \"invokeAI\" | \"invokeStream\"; alertsIndexPattern: string; anonymizationFields: { id: string; field: string; timestamp?: string | undefined; allowed?: boolean | undefined; anonymized?: boolean | undefined; updatedAt?: string | undefined; updatedBy?: string | undefined; createdAt?: string | undefined; createdBy?: string | undefined; namespace?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; langSmithProject?: string | undefined; langSmithApiKey?: string | undefined; model?: string | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; }>" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts", "deprecated": false, @@ -3126,13 +3417,73 @@ "label": "AttackDiscoveryPostResponse", "description": [], "signature": [ - "Zod.ZodObject<{ connector_id: Zod.ZodOptional<Zod.ZodString>; alertsContextCount: Zod.ZodOptional<Zod.ZodNumber>; attackDiscoveries: Zod.ZodOptional<Zod.ZodArray<Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; mitreAttackTactics?: string[] | undefined; }, { title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; mitreAttackTactics?: string[] | undefined; }>, \"many\">>; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; status: Zod.ZodOptional<Zod.ZodString>; trace_data: Zod.ZodOptional<Zod.ZodObject<{ transactionId: Zod.ZodOptional<Zod.ZodString>; traceId: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { transactionId?: string | undefined; traceId?: string | undefined; }, { transactionId?: string | undefined; traceId?: string | undefined; }>>; }, \"strip\", Zod.ZodTypeAny, { connector_id?: string | undefined; alertsContextCount?: number | undefined; attackDiscoveries?: { title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; mitreAttackTactics?: string[] | undefined; }[] | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; status?: string | undefined; trace_data?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }, { connector_id?: string | undefined; alertsContextCount?: number | undefined; attackDiscoveries?: { title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; mitreAttackTactics?: string[] | undefined; }[] | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; status?: string | undefined; trace_data?: { transactionId?: string | undefined; traceId?: string | undefined; } | undefined; }>" + "Zod.ZodObject<{ id: Zod.ZodString; timestamp: Zod.ZodOptional<Zod.ZodString>; updatedAt: Zod.ZodOptional<Zod.ZodString>; alertsContextCount: Zod.ZodOptional<Zod.ZodNumber>; createdAt: Zod.ZodString; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; users: Zod.ZodArray<Zod.ZodObject<{ id: Zod.ZodOptional<Zod.ZodString>; name: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id?: string | undefined; name?: string | undefined; }, { id?: string | undefined; name?: string | undefined; }>, \"many\">; status: Zod.ZodEnum<[\"running\", \"succeeded\", \"failed\", \"canceled\"]>; attackDiscoveries: Zod.ZodArray<Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; id: Zod.ZodOptional<Zod.ZodString>; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; timestamp: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }>, \"many\">; apiConfig: Zod.ZodObject<{ connectorId: Zod.ZodString; actionTypeId: Zod.ZodString; defaultSystemPromptId: Zod.ZodOptional<Zod.ZodString>; provider: Zod.ZodOptional<Zod.ZodEnum<[\"OpenAI\", \"Azure OpenAI\"]>>; model: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }>; namespace: Zod.ZodString; backingIndex: Zod.ZodString; generationIntervals: Zod.ZodArray<Zod.ZodObject<{ date: Zod.ZodString; durationMs: Zod.ZodNumber; }, \"strip\", Zod.ZodTypeAny, { date: string; durationMs: number; }, { date: string; durationMs: number; }>, \"many\">; averageIntervalMs: Zod.ZodNumber; failureReason: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }, { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }>" ], "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/post_attack_discovery_route.gen.ts", "deprecated": false, "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryResponse", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryResponse", + "description": [], + "signature": [ + "Zod.ZodObject<{ id: Zod.ZodString; timestamp: Zod.ZodOptional<Zod.ZodString>; updatedAt: Zod.ZodOptional<Zod.ZodString>; alertsContextCount: Zod.ZodOptional<Zod.ZodNumber>; createdAt: Zod.ZodString; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; users: Zod.ZodArray<Zod.ZodObject<{ id: Zod.ZodOptional<Zod.ZodString>; name: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id?: string | undefined; name?: string | undefined; }, { id?: string | undefined; name?: string | undefined; }>, \"many\">; status: Zod.ZodEnum<[\"running\", \"succeeded\", \"failed\", \"canceled\"]>; attackDiscoveries: Zod.ZodArray<Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; id: Zod.ZodOptional<Zod.ZodString>; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; timestamp: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }>, \"many\">; apiConfig: Zod.ZodObject<{ connectorId: Zod.ZodString; actionTypeId: Zod.ZodString; defaultSystemPromptId: Zod.ZodOptional<Zod.ZodString>; provider: Zod.ZodOptional<Zod.ZodEnum<[\"OpenAI\", \"Azure OpenAI\"]>>; model: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }>; namespace: Zod.ZodString; backingIndex: Zod.ZodString; generationIntervals: Zod.ZodArray<Zod.ZodObject<{ date: Zod.ZodString; durationMs: Zod.ZodNumber; }, \"strip\", Zod.ZodTypeAny, { date: string; durationMs: number; }, { date: string; durationMs: number; }>, \"many\">; averageIntervalMs: Zod.ZodNumber; failureReason: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }, { id: string; namespace: string; createdAt: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; users: { id?: string | undefined; name?: string | undefined; }[]; apiConfig: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }; attackDiscoveries: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[]; backingIndex: string; generationIntervals: { date: string; durationMs: number; }[]; averageIntervalMs: number; timestamp?: string | undefined; updatedAt?: string | undefined; alertsContextCount?: number | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; failureReason?: string | undefined; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryStatus", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryStatus", + "description": [], + "signature": [ + "Zod.ZodEnum<[\"running\", \"succeeded\", \"failed\", \"canceled\"]>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryStatusEnum", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryStatusEnum", + "description": [], + "signature": [ + "{ running: \"running\"; succeeded: \"succeeded\"; failed: \"failed\"; canceled: \"canceled\"; }" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.AttackDiscoveryUpdateProps", + "type": "Object", + "tags": [], + "label": "AttackDiscoveryUpdateProps", + "description": [], + "signature": [ + "Zod.ZodObject<{ id: Zod.ZodString; apiConfig: Zod.ZodOptional<Zod.ZodObject<{ connectorId: Zod.ZodString; actionTypeId: Zod.ZodString; defaultSystemPromptId: Zod.ZodOptional<Zod.ZodString>; provider: Zod.ZodOptional<Zod.ZodEnum<[\"OpenAI\", \"Azure OpenAI\"]>>; model: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }, { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; }>>; alertsContextCount: Zod.ZodOptional<Zod.ZodNumber>; attackDiscoveries: Zod.ZodOptional<Zod.ZodArray<Zod.ZodObject<{ alertIds: Zod.ZodArray<Zod.ZodString, \"many\">; id: Zod.ZodOptional<Zod.ZodString>; detailsMarkdown: Zod.ZodString; entitySummaryMarkdown: Zod.ZodString; mitreAttackTactics: Zod.ZodOptional<Zod.ZodArray<Zod.ZodString, \"many\">>; summaryMarkdown: Zod.ZodString; title: Zod.ZodString; timestamp: Zod.ZodString; }, \"strip\", Zod.ZodTypeAny, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }, { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }>, \"many\">>; status: Zod.ZodEnum<[\"running\", \"succeeded\", \"failed\", \"canceled\"]>; replacements: Zod.ZodOptional<Zod.ZodObject<{}, \"strip\", Zod.ZodString, Zod.objectOutputType<{}, Zod.ZodString, \"strip\">, Zod.objectInputType<{}, Zod.ZodString, \"strip\">>>; generationIntervals: Zod.ZodOptional<Zod.ZodArray<Zod.ZodObject<{ date: Zod.ZodString; durationMs: Zod.ZodNumber; }, \"strip\", Zod.ZodTypeAny, { date: string; durationMs: number; }, { date: string; durationMs: number; }>, \"many\">>; backingIndex: Zod.ZodString; failureReason: Zod.ZodOptional<Zod.ZodString>; }, \"strip\", Zod.ZodTypeAny, { id: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; backingIndex: string; apiConfig?: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; } | undefined; alertsContextCount?: number | undefined; attackDiscoveries?: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[] | undefined; replacements?: Zod.objectOutputType<{}, Zod.ZodString, \"strip\"> | undefined; generationIntervals?: { date: string; durationMs: number; }[] | undefined; failureReason?: string | undefined; }, { id: string; status: \"running\" | \"succeeded\" | \"failed\" | \"canceled\"; backingIndex: string; apiConfig?: { connectorId: string; actionTypeId: string; defaultSystemPromptId?: string | undefined; provider?: \"OpenAI\" | \"Azure OpenAI\" | undefined; model?: string | undefined; } | undefined; alertsContextCount?: number | undefined; attackDiscoveries?: { timestamp: string; title: string; alertIds: string[]; detailsMarkdown: string; entitySummaryMarkdown: string; summaryMarkdown: string; id?: string | undefined; mitreAttackTactics?: string[] | undefined; }[] | undefined; replacements?: Zod.objectInputType<{}, Zod.ZodString, \"strip\"> | undefined; generationIntervals?: { date: string; durationMs: number; }[] | undefined; failureReason?: string | undefined; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.BulkActionBase", @@ -3810,6 +4161,21 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/elastic-assistant-common", + "id": "def-common.GenerationInterval", + "type": "Object", + "tags": [], + "label": "GenerationInterval", + "description": [], + "signature": [ + "Zod.ZodObject<{ date: Zod.ZodString; durationMs: Zod.ZodNumber; }, \"strip\", Zod.ZodTypeAny, { date: string; durationMs: number; }, { date: string; durationMs: number; }>" + ], + "path": "x-pack/packages/kbn-elastic-assistant-common/impl/schemas/attack_discovery/common_attributes.gen.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/elastic-assistant-common", "id": "def-common.GetCapabilitiesResponse", diff --git a/api_docs/kbn_elastic_assistant_common.mdx b/api_docs/kbn_elastic_assistant_common.mdx index 2a47e5325d47f..942d9d63a39d6 100644 --- a/api_docs/kbn_elastic_assistant_common.mdx +++ b/api_docs/kbn_elastic_assistant_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-elastic-assistant-common title: "@kbn/elastic-assistant-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/elastic-assistant-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/elastic-assistant-common'] --- import kbnElasticAssistantCommonObj from './kbn_elastic_assistant_common.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 305 | 0 | 286 | 0 | +| 329 | 0 | 307 | 0 | ## Common diff --git a/api_docs/kbn_entities_schema.mdx b/api_docs/kbn_entities_schema.mdx index b5efa062eed7b..dbe6d7810b941 100644 --- a/api_docs/kbn_entities_schema.mdx +++ b/api_docs/kbn_entities_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-entities-schema title: "@kbn/entities-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/entities-schema plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/entities-schema'] --- import kbnEntitiesSchemaObj from './kbn_entities_schema.devdocs.json'; diff --git a/api_docs/kbn_es.mdx b/api_docs/kbn_es.mdx index 36008c1d52edd..0a17b1b9c57f2 100644 --- a/api_docs/kbn_es.mdx +++ b/api_docs/kbn_es.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es title: "@kbn/es" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es'] --- import kbnEsObj from './kbn_es.devdocs.json'; diff --git a/api_docs/kbn_es_archiver.mdx b/api_docs/kbn_es_archiver.mdx index 8c97edb1a7b3d..c36f2ebaff934 100644 --- a/api_docs/kbn_es_archiver.mdx +++ b/api_docs/kbn_es_archiver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-archiver title: "@kbn/es-archiver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-archiver plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-archiver'] --- import kbnEsArchiverObj from './kbn_es_archiver.devdocs.json'; diff --git a/api_docs/kbn_es_errors.mdx b/api_docs/kbn_es_errors.mdx index c6de64fc8f21b..5b9217b194a93 100644 --- a/api_docs/kbn_es_errors.mdx +++ b/api_docs/kbn_es_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-errors title: "@kbn/es-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-errors plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-errors'] --- import kbnEsErrorsObj from './kbn_es_errors.devdocs.json'; diff --git a/api_docs/kbn_es_query.mdx b/api_docs/kbn_es_query.mdx index a3455fa33de93..89e47be6af7c7 100644 --- a/api_docs/kbn_es_query.mdx +++ b/api_docs/kbn_es_query.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-query title: "@kbn/es-query" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-query plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-query'] --- import kbnEsQueryObj from './kbn_es_query.devdocs.json'; diff --git a/api_docs/kbn_es_types.mdx b/api_docs/kbn_es_types.mdx index 56754c4c3268d..3fde5d36b9d28 100644 --- a/api_docs/kbn_es_types.mdx +++ b/api_docs/kbn_es_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-es-types title: "@kbn/es-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/es-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/es-types'] --- import kbnEsTypesObj from './kbn_es_types.devdocs.json'; diff --git a/api_docs/kbn_eslint_plugin_imports.mdx b/api_docs/kbn_eslint_plugin_imports.mdx index 2066ecda55ac9..0c74b839f6dca 100644 --- a/api_docs/kbn_eslint_plugin_imports.mdx +++ b/api_docs/kbn_eslint_plugin_imports.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-eslint-plugin-imports title: "@kbn/eslint-plugin-imports" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/eslint-plugin-imports plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/eslint-plugin-imports'] --- import kbnEslintPluginImportsObj from './kbn_eslint_plugin_imports.devdocs.json'; diff --git a/api_docs/kbn_esql_ast.mdx b/api_docs/kbn_esql_ast.mdx index 07bb5be54dbf1..940d0c66a7ee1 100644 --- a/api_docs/kbn_esql_ast.mdx +++ b/api_docs/kbn_esql_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-ast title: "@kbn/esql-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-ast plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-ast'] --- import kbnEsqlAstObj from './kbn_esql_ast.devdocs.json'; diff --git a/api_docs/kbn_esql_utils.mdx b/api_docs/kbn_esql_utils.mdx index 269b6b2d39d6a..7d263e2cf2111 100644 --- a/api_docs/kbn_esql_utils.mdx +++ b/api_docs/kbn_esql_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-utils title: "@kbn/esql-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-utils'] --- import kbnEsqlUtilsObj from './kbn_esql_utils.devdocs.json'; diff --git a/api_docs/kbn_esql_validation_autocomplete.mdx b/api_docs/kbn_esql_validation_autocomplete.mdx index e4b58d95fe8fd..0c6afe5f1b14a 100644 --- a/api_docs/kbn_esql_validation_autocomplete.mdx +++ b/api_docs/kbn_esql_validation_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-esql-validation-autocomplete title: "@kbn/esql-validation-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/esql-validation-autocomplete plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/esql-validation-autocomplete'] --- import kbnEsqlValidationAutocompleteObj from './kbn_esql_validation_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_common.mdx b/api_docs/kbn_event_annotation_common.mdx index ccc246a6a1786..acd8f91383fe9 100644 --- a/api_docs/kbn_event_annotation_common.mdx +++ b/api_docs/kbn_event_annotation_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-common title: "@kbn/event-annotation-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-common'] --- import kbnEventAnnotationCommonObj from './kbn_event_annotation_common.devdocs.json'; diff --git a/api_docs/kbn_event_annotation_components.mdx b/api_docs/kbn_event_annotation_components.mdx index 3cae2992368fc..6cc7e27b88cb7 100644 --- a/api_docs/kbn_event_annotation_components.mdx +++ b/api_docs/kbn_event_annotation_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-event-annotation-components title: "@kbn/event-annotation-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/event-annotation-components plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/event-annotation-components'] --- import kbnEventAnnotationComponentsObj from './kbn_event_annotation_components.devdocs.json'; diff --git a/api_docs/kbn_expandable_flyout.mdx b/api_docs/kbn_expandable_flyout.mdx index afbdfe8185a2b..b8e0adbb14453 100644 --- a/api_docs/kbn_expandable_flyout.mdx +++ b/api_docs/kbn_expandable_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-expandable-flyout title: "@kbn/expandable-flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/expandable-flyout plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/expandable-flyout'] --- import kbnExpandableFlyoutObj from './kbn_expandable_flyout.devdocs.json'; diff --git a/api_docs/kbn_field_types.mdx b/api_docs/kbn_field_types.mdx index 35cf43fe73e8e..1b356d021779e 100644 --- a/api_docs/kbn_field_types.mdx +++ b/api_docs/kbn_field_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-types title: "@kbn/field-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-types'] --- import kbnFieldTypesObj from './kbn_field_types.devdocs.json'; diff --git a/api_docs/kbn_field_utils.mdx b/api_docs/kbn_field_utils.mdx index cdee4a5b8939d..a3ae5c91a18a8 100644 --- a/api_docs/kbn_field_utils.mdx +++ b/api_docs/kbn_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-field-utils title: "@kbn/field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/field-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/field-utils'] --- import kbnFieldUtilsObj from './kbn_field_utils.devdocs.json'; diff --git a/api_docs/kbn_find_used_node_modules.mdx b/api_docs/kbn_find_used_node_modules.mdx index ff404f570a250..5a9505fb0845d 100644 --- a/api_docs/kbn_find_used_node_modules.mdx +++ b/api_docs/kbn_find_used_node_modules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-find-used-node-modules title: "@kbn/find-used-node-modules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/find-used-node-modules plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/find-used-node-modules'] --- import kbnFindUsedNodeModulesObj from './kbn_find_used_node_modules.devdocs.json'; diff --git a/api_docs/kbn_formatters.mdx b/api_docs/kbn_formatters.mdx index dc164379999cc..e8f7c1957dfd8 100644 --- a/api_docs/kbn_formatters.mdx +++ b/api_docs/kbn_formatters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-formatters title: "@kbn/formatters" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/formatters plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/formatters'] --- import kbnFormattersObj from './kbn_formatters.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_services.mdx b/api_docs/kbn_ftr_common_functional_services.mdx index b35a983c54892..f16437af4aa92 100644 --- a/api_docs/kbn_ftr_common_functional_services.mdx +++ b/api_docs/kbn_ftr_common_functional_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-services title: "@kbn/ftr-common-functional-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-services plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-services'] --- import kbnFtrCommonFunctionalServicesObj from './kbn_ftr_common_functional_services.devdocs.json'; diff --git a/api_docs/kbn_ftr_common_functional_ui_services.mdx b/api_docs/kbn_ftr_common_functional_ui_services.mdx index 86c7e7ac446fb..1b4ab6ccd8d45 100644 --- a/api_docs/kbn_ftr_common_functional_ui_services.mdx +++ b/api_docs/kbn_ftr_common_functional_ui_services.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ftr-common-functional-ui-services title: "@kbn/ftr-common-functional-ui-services" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ftr-common-functional-ui-services plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ftr-common-functional-ui-services'] --- import kbnFtrCommonFunctionalUiServicesObj from './kbn_ftr_common_functional_ui_services.devdocs.json'; diff --git a/api_docs/kbn_generate.mdx b/api_docs/kbn_generate.mdx index 7dcfd78972417..39495ae8aad0a 100644 --- a/api_docs/kbn_generate.mdx +++ b/api_docs/kbn_generate.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate title: "@kbn/generate" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate'] --- import kbnGenerateObj from './kbn_generate.devdocs.json'; diff --git a/api_docs/kbn_generate_console_definitions.mdx b/api_docs/kbn_generate_console_definitions.mdx index 61dfa7494c9b3..7fec07f3b2eb5 100644 --- a/api_docs/kbn_generate_console_definitions.mdx +++ b/api_docs/kbn_generate_console_definitions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-console-definitions title: "@kbn/generate-console-definitions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-console-definitions plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-console-definitions'] --- import kbnGenerateConsoleDefinitionsObj from './kbn_generate_console_definitions.devdocs.json'; diff --git a/api_docs/kbn_generate_csv.mdx b/api_docs/kbn_generate_csv.mdx index f0a06a87d1cf9..239fc053a0337 100644 --- a/api_docs/kbn_generate_csv.mdx +++ b/api_docs/kbn_generate_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-generate-csv title: "@kbn/generate-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/generate-csv plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/generate-csv'] --- import kbnGenerateCsvObj from './kbn_generate_csv.devdocs.json'; diff --git a/api_docs/kbn_grouping.mdx b/api_docs/kbn_grouping.mdx index 1e9cc4f1c5dec..a98d8aa20ed30 100644 --- a/api_docs/kbn_grouping.mdx +++ b/api_docs/kbn_grouping.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-grouping title: "@kbn/grouping" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/grouping plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/grouping'] --- import kbnGroupingObj from './kbn_grouping.devdocs.json'; diff --git a/api_docs/kbn_guided_onboarding.mdx b/api_docs/kbn_guided_onboarding.mdx index 07a08aa7f91ce..ec2c5b533a1fd 100644 --- a/api_docs/kbn_guided_onboarding.mdx +++ b/api_docs/kbn_guided_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-guided-onboarding title: "@kbn/guided-onboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/guided-onboarding plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/guided-onboarding'] --- import kbnGuidedOnboardingObj from './kbn_guided_onboarding.devdocs.json'; diff --git a/api_docs/kbn_handlebars.mdx b/api_docs/kbn_handlebars.mdx index 1f392431a1882..29eef29aa4e7f 100644 --- a/api_docs/kbn_handlebars.mdx +++ b/api_docs/kbn_handlebars.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-handlebars title: "@kbn/handlebars" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/handlebars plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/handlebars'] --- import kbnHandlebarsObj from './kbn_handlebars.devdocs.json'; diff --git a/api_docs/kbn_hapi_mocks.mdx b/api_docs/kbn_hapi_mocks.mdx index 837c8435b692d..90e600e7e6852 100644 --- a/api_docs/kbn_hapi_mocks.mdx +++ b/api_docs/kbn_hapi_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-hapi-mocks title: "@kbn/hapi-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/hapi-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/hapi-mocks'] --- import kbnHapiMocksObj from './kbn_hapi_mocks.devdocs.json'; diff --git a/api_docs/kbn_health_gateway_server.mdx b/api_docs/kbn_health_gateway_server.mdx index a5106fd4e37d4..6e47d39165ee7 100644 --- a/api_docs/kbn_health_gateway_server.mdx +++ b/api_docs/kbn_health_gateway_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-health-gateway-server title: "@kbn/health-gateway-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/health-gateway-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/health-gateway-server'] --- import kbnHealthGatewayServerObj from './kbn_health_gateway_server.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_card.mdx b/api_docs/kbn_home_sample_data_card.mdx index ddaf6d2e74730..cf92ef0146bfa 100644 --- a/api_docs/kbn_home_sample_data_card.mdx +++ b/api_docs/kbn_home_sample_data_card.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-card title: "@kbn/home-sample-data-card" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-card plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-card'] --- import kbnHomeSampleDataCardObj from './kbn_home_sample_data_card.devdocs.json'; diff --git a/api_docs/kbn_home_sample_data_tab.mdx b/api_docs/kbn_home_sample_data_tab.mdx index 841c43201705e..10850e73da780 100644 --- a/api_docs/kbn_home_sample_data_tab.mdx +++ b/api_docs/kbn_home_sample_data_tab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-home-sample-data-tab title: "@kbn/home-sample-data-tab" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/home-sample-data-tab plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/home-sample-data-tab'] --- import kbnHomeSampleDataTabObj from './kbn_home_sample_data_tab.devdocs.json'; diff --git a/api_docs/kbn_i18n.mdx b/api_docs/kbn_i18n.mdx index 2d56d082e8a1a..9f3c0c6bc74a1 100644 --- a/api_docs/kbn_i18n.mdx +++ b/api_docs/kbn_i18n.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n title: "@kbn/i18n" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n'] --- import kbnI18nObj from './kbn_i18n.devdocs.json'; diff --git a/api_docs/kbn_i18n_react.mdx b/api_docs/kbn_i18n_react.mdx index 85d776ce38da6..5e7cee6f41413 100644 --- a/api_docs/kbn_i18n_react.mdx +++ b/api_docs/kbn_i18n_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-i18n-react title: "@kbn/i18n-react" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/i18n-react plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/i18n-react'] --- import kbnI18nReactObj from './kbn_i18n_react.devdocs.json'; diff --git a/api_docs/kbn_import_resolver.mdx b/api_docs/kbn_import_resolver.mdx index 654ee13c31347..68db8af24627d 100644 --- a/api_docs/kbn_import_resolver.mdx +++ b/api_docs/kbn_import_resolver.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-import-resolver title: "@kbn/import-resolver" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/import-resolver plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/import-resolver'] --- import kbnImportResolverObj from './kbn_import_resolver.devdocs.json'; diff --git a/api_docs/kbn_index_management.mdx b/api_docs/kbn_index_management.mdx index cfe7dfecd9744..360fe02b7a088 100644 --- a/api_docs/kbn_index_management.mdx +++ b/api_docs/kbn_index_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-index-management title: "@kbn/index-management" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/index-management plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/index-management'] --- import kbnIndexManagementObj from './kbn_index_management.devdocs.json'; diff --git a/api_docs/kbn_inference_integration_flyout.mdx b/api_docs/kbn_inference_integration_flyout.mdx index 72b428e6a7fea..572394251c513 100644 --- a/api_docs/kbn_inference_integration_flyout.mdx +++ b/api_docs/kbn_inference_integration_flyout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-inference_integration_flyout title: "@kbn/inference_integration_flyout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/inference_integration_flyout plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/inference_integration_flyout'] --- import kbnInferenceIntegrationFlyoutObj from './kbn_inference_integration_flyout.devdocs.json'; diff --git a/api_docs/kbn_infra_forge.mdx b/api_docs/kbn_infra_forge.mdx index 894eaf0e762e3..06b0060fd10bd 100644 --- a/api_docs/kbn_infra_forge.mdx +++ b/api_docs/kbn_infra_forge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-infra-forge title: "@kbn/infra-forge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/infra-forge plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/infra-forge'] --- import kbnInfraForgeObj from './kbn_infra_forge.devdocs.json'; diff --git a/api_docs/kbn_interpreter.mdx b/api_docs/kbn_interpreter.mdx index 951bcd8f2375c..6092e1cb866e6 100644 --- a/api_docs/kbn_interpreter.mdx +++ b/api_docs/kbn_interpreter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-interpreter title: "@kbn/interpreter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/interpreter plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/interpreter'] --- import kbnInterpreterObj from './kbn_interpreter.devdocs.json'; diff --git a/api_docs/kbn_io_ts_utils.mdx b/api_docs/kbn_io_ts_utils.mdx index 225776a467601..546ccd5a3a3c4 100644 --- a/api_docs/kbn_io_ts_utils.mdx +++ b/api_docs/kbn_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-io-ts-utils title: "@kbn/io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/io-ts-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/io-ts-utils'] --- import kbnIoTsUtilsObj from './kbn_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_ipynb.mdx b/api_docs/kbn_ipynb.mdx index 1750a7c8e6e17..45f7836787255 100644 --- a/api_docs/kbn_ipynb.mdx +++ b/api_docs/kbn_ipynb.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ipynb title: "@kbn/ipynb" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ipynb plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ipynb'] --- import kbnIpynbObj from './kbn_ipynb.devdocs.json'; diff --git a/api_docs/kbn_jest_serializers.mdx b/api_docs/kbn_jest_serializers.mdx index 58d2e7a066c5c..85d905261b452 100644 --- a/api_docs/kbn_jest_serializers.mdx +++ b/api_docs/kbn_jest_serializers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-jest-serializers title: "@kbn/jest-serializers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/jest-serializers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/jest-serializers'] --- import kbnJestSerializersObj from './kbn_jest_serializers.devdocs.json'; diff --git a/api_docs/kbn_journeys.mdx b/api_docs/kbn_journeys.mdx index df1ecd8309793..149b31c0bc043 100644 --- a/api_docs/kbn_journeys.mdx +++ b/api_docs/kbn_journeys.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-journeys title: "@kbn/journeys" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/journeys plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/journeys'] --- import kbnJourneysObj from './kbn_journeys.devdocs.json'; diff --git a/api_docs/kbn_json_ast.mdx b/api_docs/kbn_json_ast.mdx index 998cf6891a563..18bcaf779eeae 100644 --- a/api_docs/kbn_json_ast.mdx +++ b/api_docs/kbn_json_ast.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-ast title: "@kbn/json-ast" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-ast plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-ast'] --- import kbnJsonAstObj from './kbn_json_ast.devdocs.json'; diff --git a/api_docs/kbn_json_schemas.mdx b/api_docs/kbn_json_schemas.mdx index 4f3ff01365039..58c13144367e7 100644 --- a/api_docs/kbn_json_schemas.mdx +++ b/api_docs/kbn_json_schemas.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-json-schemas title: "@kbn/json-schemas" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/json-schemas plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/json-schemas'] --- import kbnJsonSchemasObj from './kbn_json_schemas.devdocs.json'; diff --git a/api_docs/kbn_kibana_manifest_schema.mdx b/api_docs/kbn_kibana_manifest_schema.mdx index dcbac16db1cf7..b767137bed3fd 100644 --- a/api_docs/kbn_kibana_manifest_schema.mdx +++ b/api_docs/kbn_kibana_manifest_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-kibana-manifest-schema title: "@kbn/kibana-manifest-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/kibana-manifest-schema plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/kibana-manifest-schema'] --- import kbnKibanaManifestSchemaObj from './kbn_kibana_manifest_schema.devdocs.json'; diff --git a/api_docs/kbn_language_documentation_popover.mdx b/api_docs/kbn_language_documentation_popover.mdx index e875525db15ab..73df9f96f17ac 100644 --- a/api_docs/kbn_language_documentation_popover.mdx +++ b/api_docs/kbn_language_documentation_popover.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-language-documentation-popover title: "@kbn/language-documentation-popover" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/language-documentation-popover plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/language-documentation-popover'] --- import kbnLanguageDocumentationPopoverObj from './kbn_language_documentation_popover.devdocs.json'; diff --git a/api_docs/kbn_lens_embeddable_utils.mdx b/api_docs/kbn_lens_embeddable_utils.mdx index fa93e8a9552ba..f4c7ab248785b 100644 --- a/api_docs/kbn_lens_embeddable_utils.mdx +++ b/api_docs/kbn_lens_embeddable_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-embeddable-utils title: "@kbn/lens-embeddable-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-embeddable-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-embeddable-utils'] --- import kbnLensEmbeddableUtilsObj from './kbn_lens_embeddable_utils.devdocs.json'; diff --git a/api_docs/kbn_lens_formula_docs.mdx b/api_docs/kbn_lens_formula_docs.mdx index 4f2a328b239ea..b793c0f062718 100644 --- a/api_docs/kbn_lens_formula_docs.mdx +++ b/api_docs/kbn_lens_formula_docs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-lens-formula-docs title: "@kbn/lens-formula-docs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/lens-formula-docs plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/lens-formula-docs'] --- import kbnLensFormulaDocsObj from './kbn_lens_formula_docs.devdocs.json'; diff --git a/api_docs/kbn_logging.mdx b/api_docs/kbn_logging.mdx index 7a0e2da03cced..a82ccbf788f7c 100644 --- a/api_docs/kbn_logging.mdx +++ b/api_docs/kbn_logging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging title: "@kbn/logging" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging'] --- import kbnLoggingObj from './kbn_logging.devdocs.json'; diff --git a/api_docs/kbn_logging_mocks.mdx b/api_docs/kbn_logging_mocks.mdx index c4e1f76965e9b..afbc1e8478f64 100644 --- a/api_docs/kbn_logging_mocks.mdx +++ b/api_docs/kbn_logging_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-logging-mocks title: "@kbn/logging-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/logging-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/logging-mocks'] --- import kbnLoggingMocksObj from './kbn_logging_mocks.devdocs.json'; diff --git a/api_docs/kbn_managed_content_badge.mdx b/api_docs/kbn_managed_content_badge.mdx index 1bb237e06806a..12e15af2fa1da 100644 --- a/api_docs/kbn_managed_content_badge.mdx +++ b/api_docs/kbn_managed_content_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-content-badge title: "@kbn/managed-content-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-content-badge plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-content-badge'] --- import kbnManagedContentBadgeObj from './kbn_managed_content_badge.devdocs.json'; diff --git a/api_docs/kbn_managed_vscode_config.mdx b/api_docs/kbn_managed_vscode_config.mdx index 18fe70c7efc4d..f64f4b6dc5d7e 100644 --- a/api_docs/kbn_managed_vscode_config.mdx +++ b/api_docs/kbn_managed_vscode_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-managed-vscode-config title: "@kbn/managed-vscode-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/managed-vscode-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/managed-vscode-config'] --- import kbnManagedVscodeConfigObj from './kbn_managed_vscode_config.devdocs.json'; diff --git a/api_docs/kbn_management_cards_navigation.mdx b/api_docs/kbn_management_cards_navigation.mdx index e3a8480446bcd..14edc43011671 100644 --- a/api_docs/kbn_management_cards_navigation.mdx +++ b/api_docs/kbn_management_cards_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-cards-navigation title: "@kbn/management-cards-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-cards-navigation plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-cards-navigation'] --- import kbnManagementCardsNavigationObj from './kbn_management_cards_navigation.devdocs.json'; diff --git a/api_docs/kbn_management_settings_application.mdx b/api_docs/kbn_management_settings_application.mdx index 1db20eb0fb7b8..8acab4ee39918 100644 --- a/api_docs/kbn_management_settings_application.mdx +++ b/api_docs/kbn_management_settings_application.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-application title: "@kbn/management-settings-application" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-application plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-application'] --- import kbnManagementSettingsApplicationObj from './kbn_management_settings_application.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_category.mdx b/api_docs/kbn_management_settings_components_field_category.mdx index e4ac1142588cc..dd7c863ddb721 100644 --- a/api_docs/kbn_management_settings_components_field_category.mdx +++ b/api_docs/kbn_management_settings_components_field_category.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-category title: "@kbn/management-settings-components-field-category" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-category plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-category'] --- import kbnManagementSettingsComponentsFieldCategoryObj from './kbn_management_settings_components_field_category.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_input.mdx b/api_docs/kbn_management_settings_components_field_input.mdx index 0378879c97b20..d7fdd414930ca 100644 --- a/api_docs/kbn_management_settings_components_field_input.mdx +++ b/api_docs/kbn_management_settings_components_field_input.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-input title: "@kbn/management-settings-components-field-input" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-input plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-input'] --- import kbnManagementSettingsComponentsFieldInputObj from './kbn_management_settings_components_field_input.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_field_row.mdx b/api_docs/kbn_management_settings_components_field_row.mdx index dd6384492b8c1..146e6c209f17f 100644 --- a/api_docs/kbn_management_settings_components_field_row.mdx +++ b/api_docs/kbn_management_settings_components_field_row.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-field-row title: "@kbn/management-settings-components-field-row" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-field-row plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-field-row'] --- import kbnManagementSettingsComponentsFieldRowObj from './kbn_management_settings_components_field_row.devdocs.json'; diff --git a/api_docs/kbn_management_settings_components_form.mdx b/api_docs/kbn_management_settings_components_form.mdx index e1c62acf69b2f..09d93df163e5c 100644 --- a/api_docs/kbn_management_settings_components_form.mdx +++ b/api_docs/kbn_management_settings_components_form.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-components-form title: "@kbn/management-settings-components-form" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-components-form plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-components-form'] --- import kbnManagementSettingsComponentsFormObj from './kbn_management_settings_components_form.devdocs.json'; diff --git a/api_docs/kbn_management_settings_field_definition.mdx b/api_docs/kbn_management_settings_field_definition.mdx index dd932811ff7ea..11ce2adee07fa 100644 --- a/api_docs/kbn_management_settings_field_definition.mdx +++ b/api_docs/kbn_management_settings_field_definition.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-field-definition title: "@kbn/management-settings-field-definition" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-field-definition plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-field-definition'] --- import kbnManagementSettingsFieldDefinitionObj from './kbn_management_settings_field_definition.devdocs.json'; diff --git a/api_docs/kbn_management_settings_ids.mdx b/api_docs/kbn_management_settings_ids.mdx index 9c570bf7416fa..44a0c20a18a40 100644 --- a/api_docs/kbn_management_settings_ids.mdx +++ b/api_docs/kbn_management_settings_ids.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-ids title: "@kbn/management-settings-ids" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-ids plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-ids'] --- import kbnManagementSettingsIdsObj from './kbn_management_settings_ids.devdocs.json'; diff --git a/api_docs/kbn_management_settings_section_registry.mdx b/api_docs/kbn_management_settings_section_registry.mdx index 7cff7e254c887..cd55c93d7695f 100644 --- a/api_docs/kbn_management_settings_section_registry.mdx +++ b/api_docs/kbn_management_settings_section_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-section-registry title: "@kbn/management-settings-section-registry" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-section-registry plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-section-registry'] --- import kbnManagementSettingsSectionRegistryObj from './kbn_management_settings_section_registry.devdocs.json'; diff --git a/api_docs/kbn_management_settings_types.mdx b/api_docs/kbn_management_settings_types.mdx index a8c3f0e6356c5..4c656b6d54371 100644 --- a/api_docs/kbn_management_settings_types.mdx +++ b/api_docs/kbn_management_settings_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-types title: "@kbn/management-settings-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-types'] --- import kbnManagementSettingsTypesObj from './kbn_management_settings_types.devdocs.json'; diff --git a/api_docs/kbn_management_settings_utilities.mdx b/api_docs/kbn_management_settings_utilities.mdx index 2104ff5d600c0..2209ef079b00c 100644 --- a/api_docs/kbn_management_settings_utilities.mdx +++ b/api_docs/kbn_management_settings_utilities.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-settings-utilities title: "@kbn/management-settings-utilities" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-settings-utilities plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-settings-utilities'] --- import kbnManagementSettingsUtilitiesObj from './kbn_management_settings_utilities.devdocs.json'; diff --git a/api_docs/kbn_management_storybook_config.mdx b/api_docs/kbn_management_storybook_config.mdx index 312515ac170db..ca6223a7320af 100644 --- a/api_docs/kbn_management_storybook_config.mdx +++ b/api_docs/kbn_management_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-management-storybook-config title: "@kbn/management-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/management-storybook-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/management-storybook-config'] --- import kbnManagementStorybookConfigObj from './kbn_management_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_mapbox_gl.mdx b/api_docs/kbn_mapbox_gl.mdx index ab7f199a2037a..1b70879987a20 100644 --- a/api_docs/kbn_mapbox_gl.mdx +++ b/api_docs/kbn_mapbox_gl.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mapbox-gl title: "@kbn/mapbox-gl" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mapbox-gl plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mapbox-gl'] --- import kbnMapboxGlObj from './kbn_mapbox_gl.devdocs.json'; diff --git a/api_docs/kbn_maps_vector_tile_utils.mdx b/api_docs/kbn_maps_vector_tile_utils.mdx index f530ff79fe640..591a043e1504c 100644 --- a/api_docs/kbn_maps_vector_tile_utils.mdx +++ b/api_docs/kbn_maps_vector_tile_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-maps-vector-tile-utils title: "@kbn/maps-vector-tile-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/maps-vector-tile-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/maps-vector-tile-utils'] --- import kbnMapsVectorTileUtilsObj from './kbn_maps_vector_tile_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_agg_utils.mdx b/api_docs/kbn_ml_agg_utils.mdx index d08c1bc90e84b..b3294895def9d 100644 --- a/api_docs/kbn_ml_agg_utils.mdx +++ b/api_docs/kbn_ml_agg_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-agg-utils title: "@kbn/ml-agg-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-agg-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-agg-utils'] --- import kbnMlAggUtilsObj from './kbn_ml_agg_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_anomaly_utils.mdx b/api_docs/kbn_ml_anomaly_utils.mdx index 88679d1520d03..9978493487053 100644 --- a/api_docs/kbn_ml_anomaly_utils.mdx +++ b/api_docs/kbn_ml_anomaly_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-anomaly-utils title: "@kbn/ml-anomaly-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-anomaly-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-anomaly-utils'] --- import kbnMlAnomalyUtilsObj from './kbn_ml_anomaly_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_cancellable_search.mdx b/api_docs/kbn_ml_cancellable_search.mdx index c3fbf9e6853fd..ca2d5ccc67bb1 100644 --- a/api_docs/kbn_ml_cancellable_search.mdx +++ b/api_docs/kbn_ml_cancellable_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-cancellable-search title: "@kbn/ml-cancellable-search" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-cancellable-search plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-cancellable-search'] --- import kbnMlCancellableSearchObj from './kbn_ml_cancellable_search.devdocs.json'; diff --git a/api_docs/kbn_ml_category_validator.mdx b/api_docs/kbn_ml_category_validator.mdx index d5d05318c49ef..c96b97fcc030b 100644 --- a/api_docs/kbn_ml_category_validator.mdx +++ b/api_docs/kbn_ml_category_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-category-validator title: "@kbn/ml-category-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-category-validator plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-category-validator'] --- import kbnMlCategoryValidatorObj from './kbn_ml_category_validator.devdocs.json'; diff --git a/api_docs/kbn_ml_chi2test.mdx b/api_docs/kbn_ml_chi2test.mdx index dde6cc0d50095..5a92f91db202d 100644 --- a/api_docs/kbn_ml_chi2test.mdx +++ b/api_docs/kbn_ml_chi2test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-chi2test title: "@kbn/ml-chi2test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-chi2test plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-chi2test'] --- import kbnMlChi2testObj from './kbn_ml_chi2test.devdocs.json'; diff --git a/api_docs/kbn_ml_data_frame_analytics_utils.mdx b/api_docs/kbn_ml_data_frame_analytics_utils.mdx index b6f4efe0b797d..c7b9b62cd18fa 100644 --- a/api_docs/kbn_ml_data_frame_analytics_utils.mdx +++ b/api_docs/kbn_ml_data_frame_analytics_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-frame-analytics-utils title: "@kbn/ml-data-frame-analytics-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-frame-analytics-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-frame-analytics-utils'] --- import kbnMlDataFrameAnalyticsUtilsObj from './kbn_ml_data_frame_analytics_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_data_grid.mdx b/api_docs/kbn_ml_data_grid.mdx index ceb962cdbc6c0..1cd002fbfb460 100644 --- a/api_docs/kbn_ml_data_grid.mdx +++ b/api_docs/kbn_ml_data_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-data-grid title: "@kbn/ml-data-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-data-grid plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-data-grid'] --- import kbnMlDataGridObj from './kbn_ml_data_grid.devdocs.json'; diff --git a/api_docs/kbn_ml_date_picker.mdx b/api_docs/kbn_ml_date_picker.mdx index 760d8769b5bd9..7d1885e427b4d 100644 --- a/api_docs/kbn_ml_date_picker.mdx +++ b/api_docs/kbn_ml_date_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-picker title: "@kbn/ml-date-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-picker plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-picker'] --- import kbnMlDatePickerObj from './kbn_ml_date_picker.devdocs.json'; diff --git a/api_docs/kbn_ml_date_utils.mdx b/api_docs/kbn_ml_date_utils.mdx index e15caf2cd8ba1..b3b5f0c35e3a7 100644 --- a/api_docs/kbn_ml_date_utils.mdx +++ b/api_docs/kbn_ml_date_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-date-utils title: "@kbn/ml-date-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-date-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-date-utils'] --- import kbnMlDateUtilsObj from './kbn_ml_date_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_error_utils.mdx b/api_docs/kbn_ml_error_utils.mdx index f6354fcd6beb9..0fbdd5c2a0716 100644 --- a/api_docs/kbn_ml_error_utils.mdx +++ b/api_docs/kbn_ml_error_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-error-utils title: "@kbn/ml-error-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-error-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-error-utils'] --- import kbnMlErrorUtilsObj from './kbn_ml_error_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_in_memory_table.mdx b/api_docs/kbn_ml_in_memory_table.mdx index 62f5582f4ecad..13c13a67058ee 100644 --- a/api_docs/kbn_ml_in_memory_table.mdx +++ b/api_docs/kbn_ml_in_memory_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-in-memory-table title: "@kbn/ml-in-memory-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-in-memory-table plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-in-memory-table'] --- import kbnMlInMemoryTableObj from './kbn_ml_in_memory_table.devdocs.json'; diff --git a/api_docs/kbn_ml_is_defined.mdx b/api_docs/kbn_ml_is_defined.mdx index e965cd0c80d47..b934c0209f6a6 100644 --- a/api_docs/kbn_ml_is_defined.mdx +++ b/api_docs/kbn_ml_is_defined.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-defined title: "@kbn/ml-is-defined" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-defined plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-defined'] --- import kbnMlIsDefinedObj from './kbn_ml_is_defined.devdocs.json'; diff --git a/api_docs/kbn_ml_is_populated_object.mdx b/api_docs/kbn_ml_is_populated_object.mdx index cff3122afafbd..f8b71f8dc039a 100644 --- a/api_docs/kbn_ml_is_populated_object.mdx +++ b/api_docs/kbn_ml_is_populated_object.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-is-populated-object title: "@kbn/ml-is-populated-object" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-is-populated-object plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-is-populated-object'] --- import kbnMlIsPopulatedObjectObj from './kbn_ml_is_populated_object.devdocs.json'; diff --git a/api_docs/kbn_ml_kibana_theme.mdx b/api_docs/kbn_ml_kibana_theme.mdx index 67964c6cabb56..fb4bff3950fe1 100644 --- a/api_docs/kbn_ml_kibana_theme.mdx +++ b/api_docs/kbn_ml_kibana_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-kibana-theme title: "@kbn/ml-kibana-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-kibana-theme plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-kibana-theme'] --- import kbnMlKibanaThemeObj from './kbn_ml_kibana_theme.devdocs.json'; diff --git a/api_docs/kbn_ml_local_storage.mdx b/api_docs/kbn_ml_local_storage.mdx index 4811d5018eee8..4e27a9c1bd619 100644 --- a/api_docs/kbn_ml_local_storage.mdx +++ b/api_docs/kbn_ml_local_storage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-local-storage title: "@kbn/ml-local-storage" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-local-storage plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-local-storage'] --- import kbnMlLocalStorageObj from './kbn_ml_local_storage.devdocs.json'; diff --git a/api_docs/kbn_ml_nested_property.mdx b/api_docs/kbn_ml_nested_property.mdx index 6d857674947ac..0475533b38f30 100644 --- a/api_docs/kbn_ml_nested_property.mdx +++ b/api_docs/kbn_ml_nested_property.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-nested-property title: "@kbn/ml-nested-property" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-nested-property plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-nested-property'] --- import kbnMlNestedPropertyObj from './kbn_ml_nested_property.devdocs.json'; diff --git a/api_docs/kbn_ml_number_utils.mdx b/api_docs/kbn_ml_number_utils.mdx index 24f0139458a55..34bf94cb0b09f 100644 --- a/api_docs/kbn_ml_number_utils.mdx +++ b/api_docs/kbn_ml_number_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-number-utils title: "@kbn/ml-number-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-number-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-number-utils'] --- import kbnMlNumberUtilsObj from './kbn_ml_number_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_query_utils.mdx b/api_docs/kbn_ml_query_utils.mdx index 28547eefc8249..24e66f9cf0e5b 100644 --- a/api_docs/kbn_ml_query_utils.mdx +++ b/api_docs/kbn_ml_query_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-query-utils title: "@kbn/ml-query-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-query-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-query-utils'] --- import kbnMlQueryUtilsObj from './kbn_ml_query_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_random_sampler_utils.mdx b/api_docs/kbn_ml_random_sampler_utils.mdx index dcafbafcfcaef..5a7ce65d3fb1a 100644 --- a/api_docs/kbn_ml_random_sampler_utils.mdx +++ b/api_docs/kbn_ml_random_sampler_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-random-sampler-utils title: "@kbn/ml-random-sampler-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-random-sampler-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-random-sampler-utils'] --- import kbnMlRandomSamplerUtilsObj from './kbn_ml_random_sampler_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_route_utils.mdx b/api_docs/kbn_ml_route_utils.mdx index f9cb2036b389f..7155dc8a9db33 100644 --- a/api_docs/kbn_ml_route_utils.mdx +++ b/api_docs/kbn_ml_route_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-route-utils title: "@kbn/ml-route-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-route-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-route-utils'] --- import kbnMlRouteUtilsObj from './kbn_ml_route_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_runtime_field_utils.mdx b/api_docs/kbn_ml_runtime_field_utils.mdx index d6742d8f211d9..10fb3bd11ebfc 100644 --- a/api_docs/kbn_ml_runtime_field_utils.mdx +++ b/api_docs/kbn_ml_runtime_field_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-runtime-field-utils title: "@kbn/ml-runtime-field-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-runtime-field-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-runtime-field-utils'] --- import kbnMlRuntimeFieldUtilsObj from './kbn_ml_runtime_field_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_string_hash.mdx b/api_docs/kbn_ml_string_hash.mdx index 884ea580ec499..47aa098a38465 100644 --- a/api_docs/kbn_ml_string_hash.mdx +++ b/api_docs/kbn_ml_string_hash.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-string-hash title: "@kbn/ml-string-hash" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-string-hash plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-string-hash'] --- import kbnMlStringHashObj from './kbn_ml_string_hash.devdocs.json'; diff --git a/api_docs/kbn_ml_time_buckets.mdx b/api_docs/kbn_ml_time_buckets.mdx index b1dd16a7a0936..1fa08ba39bb4d 100644 --- a/api_docs/kbn_ml_time_buckets.mdx +++ b/api_docs/kbn_ml_time_buckets.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-time-buckets title: "@kbn/ml-time-buckets" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-time-buckets plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-time-buckets'] --- import kbnMlTimeBucketsObj from './kbn_ml_time_buckets.devdocs.json'; diff --git a/api_docs/kbn_ml_trained_models_utils.mdx b/api_docs/kbn_ml_trained_models_utils.mdx index 5f0a78cab0d82..8c25ed9db6c3b 100644 --- a/api_docs/kbn_ml_trained_models_utils.mdx +++ b/api_docs/kbn_ml_trained_models_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-trained-models-utils title: "@kbn/ml-trained-models-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-trained-models-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-trained-models-utils'] --- import kbnMlTrainedModelsUtilsObj from './kbn_ml_trained_models_utils.devdocs.json'; diff --git a/api_docs/kbn_ml_ui_actions.mdx b/api_docs/kbn_ml_ui_actions.mdx index 255d61d571de5..243e408ef65b7 100644 --- a/api_docs/kbn_ml_ui_actions.mdx +++ b/api_docs/kbn_ml_ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-ui-actions title: "@kbn/ml-ui-actions" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-ui-actions plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-ui-actions'] --- import kbnMlUiActionsObj from './kbn_ml_ui_actions.devdocs.json'; diff --git a/api_docs/kbn_ml_url_state.mdx b/api_docs/kbn_ml_url_state.mdx index 4bad0bb0977f0..304c8153d70db 100644 --- a/api_docs/kbn_ml_url_state.mdx +++ b/api_docs/kbn_ml_url_state.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ml-url-state title: "@kbn/ml-url-state" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ml-url-state plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ml-url-state'] --- import kbnMlUrlStateObj from './kbn_ml_url_state.devdocs.json'; diff --git a/api_docs/kbn_mock_idp_utils.mdx b/api_docs/kbn_mock_idp_utils.mdx index a3048399cd2cb..5a36a0a30a877 100644 --- a/api_docs/kbn_mock_idp_utils.mdx +++ b/api_docs/kbn_mock_idp_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-mock-idp-utils title: "@kbn/mock-idp-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/mock-idp-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/mock-idp-utils'] --- import kbnMockIdpUtilsObj from './kbn_mock_idp_utils.devdocs.json'; diff --git a/api_docs/kbn_monaco.mdx b/api_docs/kbn_monaco.mdx index 198bbace24390..235c6536ac34e 100644 --- a/api_docs/kbn_monaco.mdx +++ b/api_docs/kbn_monaco.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-monaco title: "@kbn/monaco" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/monaco plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/monaco'] --- import kbnMonacoObj from './kbn_monaco.devdocs.json'; diff --git a/api_docs/kbn_object_versioning.mdx b/api_docs/kbn_object_versioning.mdx index 1b0d4e76934b2..07c35c68c0285 100644 --- a/api_docs/kbn_object_versioning.mdx +++ b/api_docs/kbn_object_versioning.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-object-versioning title: "@kbn/object-versioning" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/object-versioning plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/object-versioning'] --- import kbnObjectVersioningObj from './kbn_object_versioning.devdocs.json'; diff --git a/api_docs/kbn_observability_alert_details.mdx b/api_docs/kbn_observability_alert_details.mdx index 0384f1b33d609..d1f17f36bace4 100644 --- a/api_docs/kbn_observability_alert_details.mdx +++ b/api_docs/kbn_observability_alert_details.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alert-details title: "@kbn/observability-alert-details" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alert-details plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alert-details'] --- import kbnObservabilityAlertDetailsObj from './kbn_observability_alert_details.devdocs.json'; diff --git a/api_docs/kbn_observability_alerting_test_data.mdx b/api_docs/kbn_observability_alerting_test_data.mdx index 883a09d3854a7..f37d6f5b679f2 100644 --- a/api_docs/kbn_observability_alerting_test_data.mdx +++ b/api_docs/kbn_observability_alerting_test_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-alerting-test-data title: "@kbn/observability-alerting-test-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-alerting-test-data plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-alerting-test-data'] --- import kbnObservabilityAlertingTestDataObj from './kbn_observability_alerting_test_data.devdocs.json'; diff --git a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx index 1cf5e3e4aee80..3db1ad8b83015 100644 --- a/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx +++ b/api_docs/kbn_observability_get_padded_alert_time_range_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-observability-get-padded-alert-time-range-util title: "@kbn/observability-get-padded-alert-time-range-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/observability-get-padded-alert-time-range-util plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/observability-get-padded-alert-time-range-util'] --- import kbnObservabilityGetPaddedAlertTimeRangeUtilObj from './kbn_observability_get_padded_alert_time_range_util.devdocs.json'; diff --git a/api_docs/kbn_openapi_bundler.mdx b/api_docs/kbn_openapi_bundler.mdx index 597d7ba62502a..a64627109d0dd 100644 --- a/api_docs/kbn_openapi_bundler.mdx +++ b/api_docs/kbn_openapi_bundler.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-bundler title: "@kbn/openapi-bundler" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-bundler plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-bundler'] --- import kbnOpenapiBundlerObj from './kbn_openapi_bundler.devdocs.json'; diff --git a/api_docs/kbn_openapi_generator.mdx b/api_docs/kbn_openapi_generator.mdx index fe3cb8e1fff7d..3428436f09ebf 100644 --- a/api_docs/kbn_openapi_generator.mdx +++ b/api_docs/kbn_openapi_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-openapi-generator title: "@kbn/openapi-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/openapi-generator plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/openapi-generator'] --- import kbnOpenapiGeneratorObj from './kbn_openapi_generator.devdocs.json'; diff --git a/api_docs/kbn_optimizer.mdx b/api_docs/kbn_optimizer.mdx index 408a316925252..e9128f5fc1340 100644 --- a/api_docs/kbn_optimizer.mdx +++ b/api_docs/kbn_optimizer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer title: "@kbn/optimizer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer'] --- import kbnOptimizerObj from './kbn_optimizer.devdocs.json'; diff --git a/api_docs/kbn_optimizer_webpack_helpers.mdx b/api_docs/kbn_optimizer_webpack_helpers.mdx index cfeac573dcdf5..7ac8e2561ac34 100644 --- a/api_docs/kbn_optimizer_webpack_helpers.mdx +++ b/api_docs/kbn_optimizer_webpack_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-optimizer-webpack-helpers title: "@kbn/optimizer-webpack-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/optimizer-webpack-helpers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/optimizer-webpack-helpers'] --- import kbnOptimizerWebpackHelpersObj from './kbn_optimizer_webpack_helpers.devdocs.json'; diff --git a/api_docs/kbn_osquery_io_ts_types.mdx b/api_docs/kbn_osquery_io_ts_types.mdx index 121131be0c7c5..15f3fc0fe9e1b 100644 --- a/api_docs/kbn_osquery_io_ts_types.mdx +++ b/api_docs/kbn_osquery_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-osquery-io-ts-types title: "@kbn/osquery-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/osquery-io-ts-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/osquery-io-ts-types'] --- import kbnOsqueryIoTsTypesObj from './kbn_osquery_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_panel_loader.mdx b/api_docs/kbn_panel_loader.mdx index 0da8f25c6bf62..91dc215211b0c 100644 --- a/api_docs/kbn_panel_loader.mdx +++ b/api_docs/kbn_panel_loader.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-panel-loader title: "@kbn/panel-loader" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/panel-loader plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/panel-loader'] --- import kbnPanelLoaderObj from './kbn_panel_loader.devdocs.json'; diff --git a/api_docs/kbn_performance_testing_dataset_extractor.mdx b/api_docs/kbn_performance_testing_dataset_extractor.mdx index 6d5a54bae5cdd..6d57babf6b141 100644 --- a/api_docs/kbn_performance_testing_dataset_extractor.mdx +++ b/api_docs/kbn_performance_testing_dataset_extractor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-performance-testing-dataset-extractor title: "@kbn/performance-testing-dataset-extractor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/performance-testing-dataset-extractor plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/performance-testing-dataset-extractor'] --- import kbnPerformanceTestingDatasetExtractorObj from './kbn_performance_testing_dataset_extractor.devdocs.json'; diff --git a/api_docs/kbn_plugin_check.mdx b/api_docs/kbn_plugin_check.mdx index 6fa41d6fc2202..0fc775561dd10 100644 --- a/api_docs/kbn_plugin_check.mdx +++ b/api_docs/kbn_plugin_check.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-check title: "@kbn/plugin-check" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-check plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-check'] --- import kbnPluginCheckObj from './kbn_plugin_check.devdocs.json'; diff --git a/api_docs/kbn_plugin_generator.mdx b/api_docs/kbn_plugin_generator.mdx index 9c34f56d091a8..3835aedae256e 100644 --- a/api_docs/kbn_plugin_generator.mdx +++ b/api_docs/kbn_plugin_generator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-generator title: "@kbn/plugin-generator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-generator plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-generator'] --- import kbnPluginGeneratorObj from './kbn_plugin_generator.devdocs.json'; diff --git a/api_docs/kbn_plugin_helpers.mdx b/api_docs/kbn_plugin_helpers.mdx index 6aee3abcd7a87..7266c6afaceb8 100644 --- a/api_docs/kbn_plugin_helpers.mdx +++ b/api_docs/kbn_plugin_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-plugin-helpers title: "@kbn/plugin-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/plugin-helpers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/plugin-helpers'] --- import kbnPluginHelpersObj from './kbn_plugin_helpers.devdocs.json'; diff --git a/api_docs/kbn_presentation_containers.mdx b/api_docs/kbn_presentation_containers.mdx index abb475a635b62..2f73c594ea9a7 100644 --- a/api_docs/kbn_presentation_containers.mdx +++ b/api_docs/kbn_presentation_containers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-containers title: "@kbn/presentation-containers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-containers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-containers'] --- import kbnPresentationContainersObj from './kbn_presentation_containers.devdocs.json'; diff --git a/api_docs/kbn_presentation_publishing.mdx b/api_docs/kbn_presentation_publishing.mdx index b54ed78c429a2..5c1ca5cb3b649 100644 --- a/api_docs/kbn_presentation_publishing.mdx +++ b/api_docs/kbn_presentation_publishing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-presentation-publishing title: "@kbn/presentation-publishing" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/presentation-publishing plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/presentation-publishing'] --- import kbnPresentationPublishingObj from './kbn_presentation_publishing.devdocs.json'; diff --git a/api_docs/kbn_profiling_utils.mdx b/api_docs/kbn_profiling_utils.mdx index 6a2d810022107..2f776a33c1930 100644 --- a/api_docs/kbn_profiling_utils.mdx +++ b/api_docs/kbn_profiling_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-profiling-utils title: "@kbn/profiling-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/profiling-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/profiling-utils'] --- import kbnProfilingUtilsObj from './kbn_profiling_utils.devdocs.json'; diff --git a/api_docs/kbn_random_sampling.mdx b/api_docs/kbn_random_sampling.mdx index d3a23410f47ce..895a050a2f832 100644 --- a/api_docs/kbn_random_sampling.mdx +++ b/api_docs/kbn_random_sampling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-random-sampling title: "@kbn/random-sampling" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/random-sampling plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/random-sampling'] --- import kbnRandomSamplingObj from './kbn_random_sampling.devdocs.json'; diff --git a/api_docs/kbn_react_field.mdx b/api_docs/kbn_react_field.mdx index 2f5c5443af3d2..129e8a052908c 100644 --- a/api_docs/kbn_react_field.mdx +++ b/api_docs/kbn_react_field.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-field title: "@kbn/react-field" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-field plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-field'] --- import kbnReactFieldObj from './kbn_react_field.devdocs.json'; diff --git a/api_docs/kbn_react_hooks.mdx b/api_docs/kbn_react_hooks.mdx index 7296f2bf62294..7d80fd3c30386 100644 --- a/api_docs/kbn_react_hooks.mdx +++ b/api_docs/kbn_react_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-hooks title: "@kbn/react-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-hooks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-hooks'] --- import kbnReactHooksObj from './kbn_react_hooks.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_common.mdx b/api_docs/kbn_react_kibana_context_common.mdx index 434af433d7f29..bb86ac55a1333 100644 --- a/api_docs/kbn_react_kibana_context_common.mdx +++ b/api_docs/kbn_react_kibana_context_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-common title: "@kbn/react-kibana-context-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-common'] --- import kbnReactKibanaContextCommonObj from './kbn_react_kibana_context_common.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_render.mdx b/api_docs/kbn_react_kibana_context_render.mdx index 03e0f8d4821e4..49e6cf1c4b210 100644 --- a/api_docs/kbn_react_kibana_context_render.mdx +++ b/api_docs/kbn_react_kibana_context_render.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-render title: "@kbn/react-kibana-context-render" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-render plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-render'] --- import kbnReactKibanaContextRenderObj from './kbn_react_kibana_context_render.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_root.mdx b/api_docs/kbn_react_kibana_context_root.mdx index 5fad2b53b8397..0f4fb12aa7834 100644 --- a/api_docs/kbn_react_kibana_context_root.mdx +++ b/api_docs/kbn_react_kibana_context_root.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-root title: "@kbn/react-kibana-context-root" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-root plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-root'] --- import kbnReactKibanaContextRootObj from './kbn_react_kibana_context_root.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_styled.mdx b/api_docs/kbn_react_kibana_context_styled.mdx index 9df478dcce520..bb5514e3950db 100644 --- a/api_docs/kbn_react_kibana_context_styled.mdx +++ b/api_docs/kbn_react_kibana_context_styled.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-styled title: "@kbn/react-kibana-context-styled" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-styled plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-styled'] --- import kbnReactKibanaContextStyledObj from './kbn_react_kibana_context_styled.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_context_theme.mdx b/api_docs/kbn_react_kibana_context_theme.mdx index bf3b8356ac603..6739436e95596 100644 --- a/api_docs/kbn_react_kibana_context_theme.mdx +++ b/api_docs/kbn_react_kibana_context_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-context-theme title: "@kbn/react-kibana-context-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-context-theme plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-context-theme'] --- import kbnReactKibanaContextThemeObj from './kbn_react_kibana_context_theme.devdocs.json'; diff --git a/api_docs/kbn_react_kibana_mount.mdx b/api_docs/kbn_react_kibana_mount.mdx index d644c9f91135d..07d03e433a78e 100644 --- a/api_docs/kbn_react_kibana_mount.mdx +++ b/api_docs/kbn_react_kibana_mount.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-react-kibana-mount title: "@kbn/react-kibana-mount" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/react-kibana-mount plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/react-kibana-mount'] --- import kbnReactKibanaMountObj from './kbn_react_kibana_mount.devdocs.json'; diff --git a/api_docs/kbn_repo_file_maps.mdx b/api_docs/kbn_repo_file_maps.mdx index 608b2291b8cbe..36e4427a87f58 100644 --- a/api_docs/kbn_repo_file_maps.mdx +++ b/api_docs/kbn_repo_file_maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-file-maps title: "@kbn/repo-file-maps" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-file-maps plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-file-maps'] --- import kbnRepoFileMapsObj from './kbn_repo_file_maps.devdocs.json'; diff --git a/api_docs/kbn_repo_linter.mdx b/api_docs/kbn_repo_linter.mdx index 2aebc0e808331..5b2d8bb37347f 100644 --- a/api_docs/kbn_repo_linter.mdx +++ b/api_docs/kbn_repo_linter.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-linter title: "@kbn/repo-linter" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-linter plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-linter'] --- import kbnRepoLinterObj from './kbn_repo_linter.devdocs.json'; diff --git a/api_docs/kbn_repo_path.mdx b/api_docs/kbn_repo_path.mdx index 7b69b9f70cea8..5aca2d42fd0fb 100644 --- a/api_docs/kbn_repo_path.mdx +++ b/api_docs/kbn_repo_path.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-path title: "@kbn/repo-path" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-path plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-path'] --- import kbnRepoPathObj from './kbn_repo_path.devdocs.json'; diff --git a/api_docs/kbn_repo_source_classifier.mdx b/api_docs/kbn_repo_source_classifier.mdx index 71b24931d057f..aca6413a2cb93 100644 --- a/api_docs/kbn_repo_source_classifier.mdx +++ b/api_docs/kbn_repo_source_classifier.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-repo-source-classifier title: "@kbn/repo-source-classifier" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/repo-source-classifier plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/repo-source-classifier'] --- import kbnRepoSourceClassifierObj from './kbn_repo_source_classifier.devdocs.json'; diff --git a/api_docs/kbn_reporting_common.mdx b/api_docs/kbn_reporting_common.mdx index ad6094b1273c3..eb220a1d983af 100644 --- a/api_docs/kbn_reporting_common.mdx +++ b/api_docs/kbn_reporting_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-common title: "@kbn/reporting-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-common'] --- import kbnReportingCommonObj from './kbn_reporting_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_csv_share_panel.mdx b/api_docs/kbn_reporting_csv_share_panel.mdx index bd4abc6182bd3..42a5013a8fdb5 100644 --- a/api_docs/kbn_reporting_csv_share_panel.mdx +++ b/api_docs/kbn_reporting_csv_share_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-csv-share-panel title: "@kbn/reporting-csv-share-panel" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-csv-share-panel plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-csv-share-panel'] --- import kbnReportingCsvSharePanelObj from './kbn_reporting_csv_share_panel.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv.mdx b/api_docs/kbn_reporting_export_types_csv.mdx index 3071c5536805c..21a728c8cc295 100644 --- a/api_docs/kbn_reporting_export_types_csv.mdx +++ b/api_docs/kbn_reporting_export_types_csv.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv title: "@kbn/reporting-export-types-csv" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv'] --- import kbnReportingExportTypesCsvObj from './kbn_reporting_export_types_csv.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_csv_common.mdx b/api_docs/kbn_reporting_export_types_csv_common.mdx index cb6af41bf87a9..41f748b6ba874 100644 --- a/api_docs/kbn_reporting_export_types_csv_common.mdx +++ b/api_docs/kbn_reporting_export_types_csv_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-csv-common title: "@kbn/reporting-export-types-csv-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-csv-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-csv-common'] --- import kbnReportingExportTypesCsvCommonObj from './kbn_reporting_export_types_csv_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf.mdx b/api_docs/kbn_reporting_export_types_pdf.mdx index 2bb2df1601b1d..1743a9932c077 100644 --- a/api_docs/kbn_reporting_export_types_pdf.mdx +++ b/api_docs/kbn_reporting_export_types_pdf.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf title: "@kbn/reporting-export-types-pdf" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf'] --- import kbnReportingExportTypesPdfObj from './kbn_reporting_export_types_pdf.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_pdf_common.mdx b/api_docs/kbn_reporting_export_types_pdf_common.mdx index 7734c42024065..77b77503a4d91 100644 --- a/api_docs/kbn_reporting_export_types_pdf_common.mdx +++ b/api_docs/kbn_reporting_export_types_pdf_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-pdf-common title: "@kbn/reporting-export-types-pdf-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-pdf-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-pdf-common'] --- import kbnReportingExportTypesPdfCommonObj from './kbn_reporting_export_types_pdf_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png.mdx b/api_docs/kbn_reporting_export_types_png.mdx index 7af8185df6767..e1637105e27d9 100644 --- a/api_docs/kbn_reporting_export_types_png.mdx +++ b/api_docs/kbn_reporting_export_types_png.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png title: "@kbn/reporting-export-types-png" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png'] --- import kbnReportingExportTypesPngObj from './kbn_reporting_export_types_png.devdocs.json'; diff --git a/api_docs/kbn_reporting_export_types_png_common.mdx b/api_docs/kbn_reporting_export_types_png_common.mdx index 7cdc739f78386..575707bda5bdf 100644 --- a/api_docs/kbn_reporting_export_types_png_common.mdx +++ b/api_docs/kbn_reporting_export_types_png_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-export-types-png-common title: "@kbn/reporting-export-types-png-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-export-types-png-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-export-types-png-common'] --- import kbnReportingExportTypesPngCommonObj from './kbn_reporting_export_types_png_common.devdocs.json'; diff --git a/api_docs/kbn_reporting_mocks_server.mdx b/api_docs/kbn_reporting_mocks_server.mdx index 4b17b10cc5c7a..0297766649140 100644 --- a/api_docs/kbn_reporting_mocks_server.mdx +++ b/api_docs/kbn_reporting_mocks_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-mocks-server title: "@kbn/reporting-mocks-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-mocks-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-mocks-server'] --- import kbnReportingMocksServerObj from './kbn_reporting_mocks_server.devdocs.json'; diff --git a/api_docs/kbn_reporting_public.mdx b/api_docs/kbn_reporting_public.mdx index b8dfd4335de9f..ef2ea64a7f4f8 100644 --- a/api_docs/kbn_reporting_public.mdx +++ b/api_docs/kbn_reporting_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-public title: "@kbn/reporting-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-public plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-public'] --- import kbnReportingPublicObj from './kbn_reporting_public.devdocs.json'; diff --git a/api_docs/kbn_reporting_server.mdx b/api_docs/kbn_reporting_server.mdx index 675c8472aef30..0cdb8536d86df 100644 --- a/api_docs/kbn_reporting_server.mdx +++ b/api_docs/kbn_reporting_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-reporting-server title: "@kbn/reporting-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/reporting-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/reporting-server'] --- import kbnReportingServerObj from './kbn_reporting_server.devdocs.json'; diff --git a/api_docs/kbn_resizable_layout.mdx b/api_docs/kbn_resizable_layout.mdx index 172c0bc64d8bc..08bca57416382 100644 --- a/api_docs/kbn_resizable_layout.mdx +++ b/api_docs/kbn_resizable_layout.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-resizable-layout title: "@kbn/resizable-layout" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/resizable-layout plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/resizable-layout'] --- import kbnResizableLayoutObj from './kbn_resizable_layout.devdocs.json'; diff --git a/api_docs/kbn_response_ops_feature_flag_service.mdx b/api_docs/kbn_response_ops_feature_flag_service.mdx index 55d79fdacab25..8b33c9c69a8ff 100644 --- a/api_docs/kbn_response_ops_feature_flag_service.mdx +++ b/api_docs/kbn_response_ops_feature_flag_service.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-response-ops-feature-flag-service title: "@kbn/response-ops-feature-flag-service" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/response-ops-feature-flag-service plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/response-ops-feature-flag-service'] --- import kbnResponseOpsFeatureFlagServiceObj from './kbn_response_ops_feature_flag_service.devdocs.json'; diff --git a/api_docs/kbn_rison.mdx b/api_docs/kbn_rison.mdx index aa773e604fe5d..9d6ac1bb7d9b1 100644 --- a/api_docs/kbn_rison.mdx +++ b/api_docs/kbn_rison.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rison title: "@kbn/rison" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rison plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rison'] --- import kbnRisonObj from './kbn_rison.devdocs.json'; diff --git a/api_docs/kbn_rollup.mdx b/api_docs/kbn_rollup.mdx index e773e9afbc362..384d8bc424365 100644 --- a/api_docs/kbn_rollup.mdx +++ b/api_docs/kbn_rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rollup title: "@kbn/rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rollup plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rollup'] --- import kbnRollupObj from './kbn_rollup.devdocs.json'; diff --git a/api_docs/kbn_router_to_openapispec.mdx b/api_docs/kbn_router_to_openapispec.mdx index 34feaad2fc107..ed370b0788d53 100644 --- a/api_docs/kbn_router_to_openapispec.mdx +++ b/api_docs/kbn_router_to_openapispec.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-to-openapispec title: "@kbn/router-to-openapispec" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-to-openapispec plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-to-openapispec'] --- import kbnRouterToOpenapispecObj from './kbn_router_to_openapispec.devdocs.json'; diff --git a/api_docs/kbn_router_utils.mdx b/api_docs/kbn_router_utils.mdx index 82ed280891c2b..eb37924a7593a 100644 --- a/api_docs/kbn_router_utils.mdx +++ b/api_docs/kbn_router_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-router-utils title: "@kbn/router-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/router-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/router-utils'] --- import kbnRouterUtilsObj from './kbn_router_utils.devdocs.json'; diff --git a/api_docs/kbn_rrule.mdx b/api_docs/kbn_rrule.mdx index 99505b6630f86..d8c3f8dec7c48 100644 --- a/api_docs/kbn_rrule.mdx +++ b/api_docs/kbn_rrule.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rrule title: "@kbn/rrule" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rrule plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rrule'] --- import kbnRruleObj from './kbn_rrule.devdocs.json'; diff --git a/api_docs/kbn_rule_data_utils.mdx b/api_docs/kbn_rule_data_utils.mdx index da77e0e06f180..b7e0f4e5d717f 100644 --- a/api_docs/kbn_rule_data_utils.mdx +++ b/api_docs/kbn_rule_data_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-rule-data-utils title: "@kbn/rule-data-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/rule-data-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/rule-data-utils'] --- import kbnRuleDataUtilsObj from './kbn_rule_data_utils.devdocs.json'; diff --git a/api_docs/kbn_saved_objects_settings.mdx b/api_docs/kbn_saved_objects_settings.mdx index 20ea2158f21a4..6a4c14ca2247e 100644 --- a/api_docs/kbn_saved_objects_settings.mdx +++ b/api_docs/kbn_saved_objects_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-saved-objects-settings title: "@kbn/saved-objects-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/saved-objects-settings plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/saved-objects-settings'] --- import kbnSavedObjectsSettingsObj from './kbn_saved_objects_settings.devdocs.json'; diff --git a/api_docs/kbn_search_api_panels.mdx b/api_docs/kbn_search_api_panels.mdx index 391caab0f8279..88fbdc8526d38 100644 --- a/api_docs/kbn_search_api_panels.mdx +++ b/api_docs/kbn_search_api_panels.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-api-panels title: "@kbn/search-api-panels" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-api-panels plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-api-panels'] --- import kbnSearchApiPanelsObj from './kbn_search_api_panels.devdocs.json'; diff --git a/api_docs/kbn_search_connectors.mdx b/api_docs/kbn_search_connectors.mdx index 5b6b7fed9a06b..8c0bcb67e3913 100644 --- a/api_docs/kbn_search_connectors.mdx +++ b/api_docs/kbn_search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-connectors title: "@kbn/search-connectors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-connectors plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-connectors'] --- import kbnSearchConnectorsObj from './kbn_search_connectors.devdocs.json'; diff --git a/api_docs/kbn_search_errors.mdx b/api_docs/kbn_search_errors.mdx index 54eadcd190803..c99b03ea42fa2 100644 --- a/api_docs/kbn_search_errors.mdx +++ b/api_docs/kbn_search_errors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-errors title: "@kbn/search-errors" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-errors plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-errors'] --- import kbnSearchErrorsObj from './kbn_search_errors.devdocs.json'; diff --git a/api_docs/kbn_search_index_documents.mdx b/api_docs/kbn_search_index_documents.mdx index 7e10a60dc7f25..ecf67bf4ab03b 100644 --- a/api_docs/kbn_search_index_documents.mdx +++ b/api_docs/kbn_search_index_documents.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-index-documents title: "@kbn/search-index-documents" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-index-documents plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-index-documents'] --- import kbnSearchIndexDocumentsObj from './kbn_search_index_documents.devdocs.json'; diff --git a/api_docs/kbn_search_response_warnings.mdx b/api_docs/kbn_search_response_warnings.mdx index 16f3c1ddf56ac..f3d52fdc94511 100644 --- a/api_docs/kbn_search_response_warnings.mdx +++ b/api_docs/kbn_search_response_warnings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-response-warnings title: "@kbn/search-response-warnings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-response-warnings plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-response-warnings'] --- import kbnSearchResponseWarningsObj from './kbn_search_response_warnings.devdocs.json'; diff --git a/api_docs/kbn_search_types.mdx b/api_docs/kbn_search_types.mdx index 28d252c5f4d14..60dc776e611a4 100644 --- a/api_docs/kbn_search_types.mdx +++ b/api_docs/kbn_search_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-search-types title: "@kbn/search-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/search-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/search-types'] --- import kbnSearchTypesObj from './kbn_search_types.devdocs.json'; diff --git a/api_docs/kbn_security_api_key_management.devdocs.json b/api_docs/kbn_security_api_key_management.devdocs.json new file mode 100644 index 0000000000000..2c2f3d3c66c73 --- /dev/null +++ b/api_docs/kbn_security_api_key_management.devdocs.json @@ -0,0 +1,1259 @@ +{ + "id": "@kbn/security-api-key-management", + "client": { + "classes": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient", + "type": "Class", + "tags": [], + "label": "APIKeysAPIClient", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.Unnamed", + "type": "Function", + "tags": [], + "label": "Constructor", + "description": [], + "signature": [ + "any" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.Unnamed.$1", + "type": "Object", + "tags": [], + "label": "http", + "description": [], + "signature": [ + { + "pluginId": "@kbn/core-http-browser", + "scope": "common", + "docId": "kibKbnCoreHttpBrowserPluginApi", + "section": "def-common.HttpSetup", + "text": "HttpSetup" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.queryApiKeys", + "type": "Function", + "tags": [], + "label": "queryApiKeys", + "description": [], + "signature": [ + "(params?: ", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.QueryApiKeyParams", + "text": "QueryApiKeyParams" + }, + " | undefined) => Promise<", + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.QueryApiKeyResult", + "text": "QueryApiKeyResult" + }, + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.queryApiKeys.$1", + "type": "Object", + "tags": [], + "label": "params", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.QueryApiKeyParams", + "text": "QueryApiKeyParams" + }, + " | undefined" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": false + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.invalidateApiKeys", + "type": "Function", + "tags": [], + "label": "invalidateApiKeys", + "description": [], + "signature": [ + "(apiKeys: ", + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.ApiKeyToInvalidate", + "text": "ApiKeyToInvalidate" + }, + "[], isAdmin?: boolean) => Promise<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.InvalidateApiKeysResponse", + "text": "InvalidateApiKeysResponse" + }, + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.invalidateApiKeys.$1", + "type": "Array", + "tags": [], + "label": "apiKeys", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.ApiKeyToInvalidate", + "text": "ApiKeyToInvalidate" + }, + "[]" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.invalidateApiKeys.$2", + "type": "boolean", + "tags": [], + "label": "isAdmin", + "description": [], + "signature": [ + "boolean" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.createApiKey", + "type": "Function", + "tags": [], + "label": "createApiKey", + "description": [], + "signature": [ + "(apiKey: ", + { + "pluginId": "@kbn/security-plugin-types-server", + "scope": "server", + "docId": "kibKbnSecurityPluginTypesServerPluginApi", + "section": "def-server.CreateAPIKeyParams", + "text": "CreateAPIKeyParams" + }, + ") => Promise<", + "SecurityCreateApiKeyResponse", + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.createApiKey.$1", + "type": "CompoundType", + "tags": [], + "label": "apiKey", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-server", + "scope": "server", + "docId": "kibKbnSecurityPluginTypesServerPluginApi", + "section": "def-server.CreateAPIKeyParams", + "text": "CreateAPIKeyParams" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.updateApiKey", + "type": "Function", + "tags": [], + "label": "updateApiKey", + "description": [], + "signature": [ + "(apiKey: ", + { + "pluginId": "@kbn/security-plugin-types-server", + "scope": "server", + "docId": "kibKbnSecurityPluginTypesServerPluginApi", + "section": "def-server.UpdateAPIKeyParams", + "text": "UpdateAPIKeyParams" + }, + ") => Promise<", + "SecurityUpdateApiKeyResponse", + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.APIKeysAPIClient.updateApiKey.$1", + "type": "CompoundType", + "tags": [], + "label": "apiKey", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-server", + "scope": "server", + "docId": "kibKbnSecurityPluginTypesServerPluginApi", + "section": "def-server.UpdateAPIKeyParams", + "text": "UpdateAPIKeyParams" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [] + } + ], + "initialIsOpen": false + } + ], + "functions": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyBadge", + "type": "Function", + "tags": [], + "label": "ApiKeyBadge", + "description": [], + "signature": [ + "({ type }: React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyBadgeProps", + "text": "ApiKeyBadgeProps" + }, + ">) => JSX.Element" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_badge.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyBadge.$1", + "type": "CompoundType", + "tags": [], + "label": "{ type }", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyBadgeProps", + "text": "ApiKeyBadgeProps" + }, + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_badge.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyCreatedCallout", + "type": "Function", + "tags": [], + "label": "ApiKeyCreatedCallout", + "description": [], + "signature": [ + "({ createdApiKey, }: React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyCreatedCalloutProps", + "text": "ApiKeyCreatedCalloutProps" + }, + ">) => JSX.Element" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_created_callout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyCreatedCallout.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n createdApiKey,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyCreatedCalloutProps", + "text": "ApiKeyCreatedCalloutProps" + }, + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_created_callout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFlyout", + "type": "Function", + "tags": [], + "label": "ApiKeyFlyout", + "description": [], + "signature": [ + "({ onSuccess, onCancel, defaultExpiration, defaultMetadata, defaultRoleDescriptors, apiKey, canManageCrossClusterApiKeys, readOnly, currentUser, isLoadingCurrentUser, }: React.PropsWithChildren<(", + "DisambiguateSet", + "<CreateApiKeyFlyoutProps, UpdateApiKeyFlyoutProps> & UpdateApiKeyFlyoutProps) | (", + "DisambiguateSet", + "<UpdateApiKeyFlyoutProps, CreateApiKeyFlyoutProps> & CreateApiKeyFlyoutProps)>) => JSX.Element" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFlyout.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n onSuccess,\n onCancel,\n defaultExpiration,\n defaultMetadata,\n defaultRoleDescriptors,\n apiKey,\n canManageCrossClusterApiKeys = false,\n readOnly = false,\n currentUser,\n isLoadingCurrentUser,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<(", + "DisambiguateSet", + "<CreateApiKeyFlyoutProps, UpdateApiKeyFlyoutProps> & UpdateApiKeyFlyoutProps) | (", + "DisambiguateSet", + "<UpdateApiKeyFlyoutProps, CreateApiKeyFlyoutProps> & CreateApiKeyFlyoutProps)>" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeySelectableTokenField", + "type": "Function", + "tags": [], + "label": "ApiKeySelectableTokenField", + "description": [], + "signature": [ + "({ createdApiKey, }: React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyCreatedCalloutProps", + "text": "ApiKeyCreatedCalloutProps" + }, + ">) => JSX.Element" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_created_callout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeySelectableTokenField.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n createdApiKey,\n}", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyCreatedCalloutProps", + "text": "ApiKeyCreatedCalloutProps" + }, + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_created_callout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyStatus", + "type": "Function", + "tags": [], + "label": "ApiKeyStatus", + "description": [], + "signature": [ + "({ expiration }: React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyStatusProps", + "text": "ApiKeyStatusProps" + }, + ">) => JSX.Element" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_status.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyStatus.$1", + "type": "CompoundType", + "tags": [], + "label": "{ expiration }", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyStatusProps", + "text": "ApiKeyStatusProps" + }, + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_status.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.mapCreateApiKeyValues", + "type": "Function", + "tags": [], + "label": "mapCreateApiKeyValues", + "description": [], + "signature": [ + "(values: ", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyFormValues", + "text": "ApiKeyFormValues" + }, + ") => ", + { + "pluginId": "@kbn/security-plugin-types-server", + "scope": "server", + "docId": "kibKbnSecurityPluginTypesServerPluginApi", + "section": "def-server.CreateAPIKeyParams", + "text": "CreateAPIKeyParams" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.mapCreateApiKeyValues.$1", + "type": "Object", + "tags": [], + "label": "values", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyFormValues", + "text": "ApiKeyFormValues" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.mapUpdateApiKeyValues", + "type": "Function", + "tags": [], + "label": "mapUpdateApiKeyValues", + "description": [], + "signature": [ + "(type: \"managed\" | \"rest\" | \"cross_cluster\", id: string, values: ", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyFormValues", + "text": "ApiKeyFormValues" + }, + ") => ", + { + "pluginId": "@kbn/security-plugin-types-server", + "scope": "server", + "docId": "kibKbnSecurityPluginTypesServerPluginApi", + "section": "def-server.UpdateAPIKeyParams", + "text": "UpdateAPIKeyParams" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.mapUpdateApiKeyValues.$1", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"managed\" | \"rest\" | \"cross_cluster\"" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.mapUpdateApiKeyValues.$2", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "signature": [ + "string" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.mapUpdateApiKeyValues.$3", + "type": "Object", + "tags": [], + "label": "values", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.ApiKeyFormValues", + "text": "ApiKeyFormValues" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.TimeToolTip", + "type": "Function", + "tags": [], + "label": "TimeToolTip", + "description": [], + "signature": [ + "({ timestamp, children }: React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.TimeToolTipProps", + "text": "TimeToolTipProps" + }, + ">) => JSX.Element" + ], + "path": "x-pack/packages/security/api_key_management/src/components/time_tool_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.TimeToolTip.$1", + "type": "CompoundType", + "tags": [], + "label": "{ timestamp, children }", + "description": [], + "signature": [ + "React.PropsWithChildren<", + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.TimeToolTipProps", + "text": "TimeToolTipProps" + }, + ">" + ], + "path": "x-pack/packages/security/api_key_management/src/components/time_tool_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyBadgeProps", + "type": "Interface", + "tags": [], + "label": "ApiKeyBadgeProps", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_badge.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyBadgeProps.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"managed\" | \"rest\" | \"cross_cluster\"" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_badge.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyCreatedCalloutProps", + "type": "Interface", + "tags": [], + "label": "ApiKeyCreatedCalloutProps", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_created_callout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyCreatedCalloutProps.createdApiKey", + "type": "Object", + "tags": [], + "label": "createdApiKey", + "description": [], + "signature": [ + "SecurityCreateApiKeyResponse" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_created_callout.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues", + "type": "Interface", + "tags": [], + "label": "ApiKeyFormValues", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.expiration", + "type": "string", + "tags": [], + "label": "expiration", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.customExpiration", + "type": "boolean", + "tags": [], + "label": "customExpiration", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.customPrivileges", + "type": "boolean", + "tags": [], + "label": "customPrivileges", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.includeMetadata", + "type": "boolean", + "tags": [], + "label": "includeMetadata", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.access", + "type": "string", + "tags": [], + "label": "access", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.role_descriptors", + "type": "string", + "tags": [], + "label": "role_descriptors", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFormValues.metadata", + "type": "string", + "tags": [], + "label": "metadata", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.InvalidateApiKeysResponse", + "type": "Interface", + "tags": [], + "label": "InvalidateApiKeysResponse", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.InvalidateApiKeysResponse.itemsInvalidated", + "type": "Array", + "tags": [], + "label": "itemsInvalidated", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.ApiKeyToInvalidate", + "text": "ApiKeyToInvalidate" + }, + "[]" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.InvalidateApiKeysResponse.errors", + "type": "Array", + "tags": [], + "label": "errors", + "description": [], + "signature": [ + "any[]" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeyParams", + "type": "Interface", + "tags": [], + "label": "QueryApiKeyParams", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeyParams.query", + "type": "Object", + "tags": [], + "label": "query", + "description": [], + "signature": [ + "QueryContainer" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeyParams.from", + "type": "number", + "tags": [], + "label": "from", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeyParams.size", + "type": "number", + "tags": [], + "label": "size", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeyParams.sort", + "type": "Object", + "tags": [], + "label": "sort", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.QueryApiKeySortOptions", + "text": "QueryApiKeySortOptions" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeyParams.filters", + "type": "Object", + "tags": [], + "label": "filters", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-api-key-management", + "scope": "public", + "docId": "kibKbnSecurityApiKeyManagementPluginApi", + "section": "def-public.QueryFilters", + "text": "QueryFilters" + } + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeySortOptions", + "type": "Interface", + "tags": [], + "label": "QueryApiKeySortOptions", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeySortOptions.field", + "type": "CompoundType", + "tags": [], + "label": "field", + "description": [], + "signature": [ + "\"id\" | \"type\" | \"name\" | \"username\" | \"metadata\" | \"expired\" | \"creation\" | \"expiration\" | \"role_descriptors\" | \"realm\" | \"invalidated\" | \"limited_by\" | \"_sort\"" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryApiKeySortOptions.direction", + "type": "CompoundType", + "tags": [], + "label": "direction", + "description": [], + "signature": [ + "\"asc\" | \"desc\"" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryFilters", + "type": "Interface", + "tags": [], + "label": "QueryFilters", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryFilters.usernames", + "type": "Array", + "tags": [], + "label": "usernames", + "description": [], + "signature": [ + "string[] | undefined" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryFilters.type", + "type": "CompoundType", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"managed\" | \"rest\" | \"cross_cluster\" | undefined" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.QueryFilters.expired", + "type": "CompoundType", + "tags": [], + "label": "expired", + "description": [], + "signature": [ + "boolean | undefined" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_keys_api_client.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.TimeToolTipProps", + "type": "Interface", + "tags": [], + "label": "TimeToolTipProps", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/time_tool_tip.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.TimeToolTipProps.timestamp", + "type": "number", + "tags": [], + "label": "timestamp", + "description": [], + "path": "x-pack/packages/security/api_key_management/src/components/time_tool_tip.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyFlyoutProps", + "type": "Type", + "tags": [], + "label": "ApiKeyFlyoutProps", + "description": [], + "signature": [ + "(", + "DisambiguateSet", + "<CreateApiKeyFlyoutProps, UpdateApiKeyFlyoutProps> & UpdateApiKeyFlyoutProps) | (", + "DisambiguateSet", + "<UpdateApiKeyFlyoutProps, CreateApiKeyFlyoutProps> & CreateApiKeyFlyoutProps)" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_flyout.tsx", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.ApiKeyStatusProps", + "type": "Type", + "tags": [], + "label": "ApiKeyStatusProps", + "description": [], + "signature": [ + "{ expiration?: number | undefined; }" + ], + "path": "x-pack/packages/security/api_key_management/src/components/api_key_status.tsx", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.CreateAPIKeyParams", + "type": "Type", + "tags": [], + "label": "CreateAPIKeyParams", + "description": [], + "signature": [ + "Readonly<{ type?: \"rest\" | undefined; metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { name: string; role_descriptors: Record<string, Readonly<{} & {}>>; }> | Readonly<{ type?: \"rest\" | undefined; metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { name: string; kibana_role_descriptors: Record<string, Readonly<{} & { kibana: Readonly<{ base?: string[] | undefined; feature?: Record<string, string[]> | undefined; } & { spaces: string[] | \"*\"[]; }>[]; elasticsearch: Readonly<{ cluster?: string[] | undefined; indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; }>[] | undefined; remote_cluster?: Readonly<{} & { privileges: string[]; clusters: string[]; }>[] | undefined; remote_indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; clusters: string[]; }>[] | undefined; run_as?: string[] | undefined; } & {}>; }>>; }> | Readonly<{ metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { type: \"cross_cluster\"; name: string; access: Readonly<{ search?: Readonly<{ query?: any; field_security?: any; allow_restricted_indices?: boolean | undefined; } & { names: string[]; }>[] | undefined; replication?: Readonly<{} & { names: string[]; }>[] | undefined; } & {}>; }>" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.CreateAPIKeyResult", + "type": "Type", + "tags": [], + "label": "CreateAPIKeyResult", + "description": [ + "\nResponse of Kibana Create API key endpoint." + ], + "signature": [ + "SecurityCreateApiKeyResponse" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.UpdateAPIKeyParams", + "type": "Type", + "tags": [], + "label": "UpdateAPIKeyParams", + "description": [ + "\nRequest body of Kibana Update API key endpoint." + ], + "signature": [ + "Readonly<{ type?: \"rest\" | undefined; metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { id: string; role_descriptors: Record<string, Readonly<{} & {}>>; }> | Readonly<{ metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { id: string; type: \"cross_cluster\"; access: Readonly<{ search?: Readonly<{ query?: any; field_security?: any; allow_restricted_indices?: boolean | undefined; } & { names: string[]; }>[] | undefined; replication?: Readonly<{} & { names: string[]; }>[] | undefined; } & {}>; }> | Readonly<{ type?: \"rest\" | undefined; metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { id: string; kibana_role_descriptors: Record<string, Readonly<{} & { kibana: Readonly<{ base?: string[] | undefined; feature?: Record<string, string[]> | undefined; } & { spaces: string[] | \"*\"[]; }>[]; elasticsearch: Readonly<{ cluster?: string[] | undefined; indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; }>[] | undefined; remote_cluster?: Readonly<{} & { privileges: string[]; clusters: string[]; }>[] | undefined; remote_indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; clusters: string[]; }>[] | undefined; run_as?: string[] | undefined; } & {}>; }>>; }>" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-api-key-management", + "id": "def-public.UpdateAPIKeyResult", + "type": "Type", + "tags": [], + "label": "UpdateAPIKeyResult", + "description": [ + "\nResponse of Kibana Update API key endpoint." + ], + "signature": [ + "SecurityUpdateApiKeyResponse" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + } + ], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_security_api_key_management.mdx b/api_docs/kbn_security_api_key_management.mdx new file mode 100644 index 0000000000000..182ae1226f8a4 --- /dev/null +++ b/api_docs/kbn_security_api_key_management.mdx @@ -0,0 +1,39 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSecurityApiKeyManagementPluginApi +slug: /kibana-dev-docs/api/kbn-security-api-key-management +title: "@kbn/security-api-key-management" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/security-api-key-management plugin +date: 2024-06-26 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-api-key-management'] +--- +import kbnSecurityApiKeyManagementObj from './kbn_security_api_key_management.devdocs.json'; + + + +Contact [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 68 | 0 | 65 | 0 | + +## Client + +### Functions +<DocDefinitionList data={kbnSecurityApiKeyManagementObj.client.functions}/> + +### Classes +<DocDefinitionList data={kbnSecurityApiKeyManagementObj.client.classes}/> + +### Interfaces +<DocDefinitionList data={kbnSecurityApiKeyManagementObj.client.interfaces}/> + +### Consts, variables and types +<DocDefinitionList data={kbnSecurityApiKeyManagementObj.client.misc}/> + diff --git a/api_docs/kbn_security_form_components.devdocs.json b/api_docs/kbn_security_form_components.devdocs.json new file mode 100644 index 0000000000000..e6456ca9c7abd --- /dev/null +++ b/api_docs/kbn_security_form_components.devdocs.json @@ -0,0 +1,727 @@ +{ + "id": "@kbn/security-form-components", + "client": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "server": { + "classes": [], + "functions": [], + "interfaces": [], + "enums": [], + "misc": [], + "objects": [] + }, + "common": { + "classes": [], + "functions": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.createFieldValidator", + "type": "Function", + "tags": [], + "label": "createFieldValidator", + "description": [], + "signature": [ + "(options: ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.ValidateOptions", + "text": "ValidateOptions" + }, + ") => ", + "FieldValidator" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.createFieldValidator.$1", + "type": "Object", + "tags": [], + "label": "options", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.ValidateOptions", + "text": "ValidateOptions" + } + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormChangesProvider", + "type": "Function", + "tags": [], + "label": "FormChangesProvider", + "description": [], + "signature": [ + "React.ProviderExoticComponent<React.ProviderProps<", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormChangesProps", + "text": "FormChangesProps" + }, + " | undefined>>" + ], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormChangesProvider.$1", + "type": "Uncategorized", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "P" + ], + "path": "node_modules/@types/react/index.d.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormField", + "type": "Function", + "tags": [ + "throws" + ], + "label": "FormField", + "description": [ + "\nPolymorphic component that renders a form field with all state required for inline validation.\n" + ], + "signature": [ + "({\n as,\n validate,\n onBlur,\n ...rest\n}: ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormFieldProps", + "text": "FormFieldProps" + }, + "<T> & Omit<React.PropsWithoutRef<React.ComponentProps<T>>, keyof ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormFieldProps", + "text": "FormFieldProps" + }, + "<T>>) => JSX.Element" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormField.$1", + "type": "CompoundType", + "tags": [], + "label": "{\n as,\n validate,\n onBlur,\n ...rest\n}", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormFieldProps", + "text": "FormFieldProps" + }, + "<T> & Omit<React.PropsWithoutRef<React.ComponentProps<T>>, keyof ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormFieldProps", + "text": "FormFieldProps" + }, + "<T>>" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormLabel", + "type": "Function", + "tags": [ + "throws", + "throws" + ], + "label": "FormLabel", + "description": [ + "\nComponent that visually indicates whether a field value has changed.\n" + ], + "signature": [ + "(props: React.PropsWithChildren<React.PropsWithChildren<", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormLabelProps", + "text": "FormLabelProps" + }, + ">>) => JSX.Element" + ], + "path": "x-pack/packages/security/form_components/src/form_label.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormLabel.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "React.PropsWithChildren<React.PropsWithChildren<", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormLabelProps", + "text": "FormLabelProps" + }, + ">>" + ], + "path": "x-pack/packages/security/form_components/src/form_label.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormRow", + "type": "Function", + "tags": [ + "throws", + "throws" + ], + "label": "FormRow", + "description": [ + "\nComponent that renders a form row with all error states for inline validation.\n" + ], + "signature": [ + "(props: React.PropsWithChildren<((", + "DisambiguateSet", + "<LabelProps, LegendProps> & { labelType?: \"legend\" | undefined; } & ", + "CommonProps", + " & { display?: \"center\" | \"row\" | \"rowCompressed\" | \"columnCompressed\" | \"centerCompressed\" | \"columnCompressedSwitch\" | undefined; hasEmptyLabelSpace?: boolean | undefined; fullWidth?: boolean | undefined; describedByIds?: string[] | undefined; hasChildLabel?: boolean | undefined; children: React.ReactElement<any, string | React.JSXElementConstructor<any>>; label?: React.ReactNode; labelAppend?: any; id?: string | undefined; isInvalid?: boolean | undefined; error?: React.ReactNode | React.ReactNode[]; helpText?: React.ReactNode | React.ReactNode[]; isDisabled?: boolean | undefined; } & Omit<React.HTMLAttributes<HTMLFieldSetElement>, \"disabled\">) | (", + "DisambiguateSet", + "<LegendProps, LabelProps> & { labelType?: \"label\" | undefined; } & ", + "CommonProps", + " & { display?: \"center\" | \"row\" | \"rowCompressed\" | \"columnCompressed\" | \"centerCompressed\" | \"columnCompressedSwitch\" | undefined; hasEmptyLabelSpace?: boolean | undefined; fullWidth?: boolean | undefined; describedByIds?: string[] | undefined; hasChildLabel?: boolean | undefined; children: React.ReactElement<any, string | React.JSXElementConstructor<any>>; label?: React.ReactNode; labelAppend?: any; id?: string | undefined; isInvalid?: boolean | undefined; error?: React.ReactNode | React.ReactNode[]; helpText?: React.ReactNode | React.ReactNode[]; isDisabled?: boolean | undefined; } & React.HTMLAttributes<HTMLDivElement>)) & ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormRowProps", + "text": "FormRowProps" + }, + ">) => JSX.Element" + ], + "path": "x-pack/packages/security/form_components/src/form_row.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormRow.$1", + "type": "CompoundType", + "tags": [], + "label": "props", + "description": [], + "signature": [ + "React.PropsWithChildren<((", + "DisambiguateSet", + "<LabelProps, LegendProps> & { labelType?: \"legend\" | undefined; } & ", + "CommonProps", + " & { display?: \"center\" | \"row\" | \"rowCompressed\" | \"columnCompressed\" | \"centerCompressed\" | \"columnCompressedSwitch\" | undefined; hasEmptyLabelSpace?: boolean | undefined; fullWidth?: boolean | undefined; describedByIds?: string[] | undefined; hasChildLabel?: boolean | undefined; children: React.ReactElement<any, string | React.JSXElementConstructor<any>>; label?: React.ReactNode; labelAppend?: any; id?: string | undefined; isInvalid?: boolean | undefined; error?: React.ReactNode | React.ReactNode[]; helpText?: React.ReactNode | React.ReactNode[]; isDisabled?: boolean | undefined; } & Omit<React.HTMLAttributes<HTMLFieldSetElement>, \"disabled\">) | (", + "DisambiguateSet", + "<LegendProps, LabelProps> & { labelType?: \"label\" | undefined; } & ", + "CommonProps", + " & { display?: \"center\" | \"row\" | \"rowCompressed\" | \"columnCompressed\" | \"centerCompressed\" | \"columnCompressedSwitch\" | undefined; hasEmptyLabelSpace?: boolean | undefined; fullWidth?: boolean | undefined; describedByIds?: string[] | undefined; hasChildLabel?: boolean | undefined; children: React.ReactElement<any, string | React.JSXElementConstructor<any>>; label?: React.ReactNode; labelAppend?: any; id?: string | undefined; isInvalid?: boolean | undefined; error?: React.ReactNode | React.ReactNode[]; helpText?: React.ReactNode | React.ReactNode[]; isDisabled?: boolean | undefined; } & React.HTMLAttributes<HTMLDivElement>)) & ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormRowProps", + "text": "FormRowProps" + }, + ">" + ], + "path": "x-pack/packages/security/form_components/src/form_row.tsx", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.OptionalText", + "type": "Function", + "tags": [], + "label": "OptionalText", + "description": [], + "signature": [ + "() => JSX.Element" + ], + "path": "x-pack/packages/security/form_components/src/form_row.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.useFormChanges", + "type": "Function", + "tags": [], + "label": "useFormChanges", + "description": [ + "\nCustom React hook that allows tracking changes within a form.\n" + ], + "signature": [ + "() => ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormChangesProps", + "text": "FormChangesProps" + } + ], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.useFormChangesContext", + "type": "Function", + "tags": [ + "throws" + ], + "label": "useFormChangesContext", + "description": [ + "\nCustom React hook that returns all @see FormChangesProps state from context.\n" + ], + "signature": [ + "() => ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormChangesProps", + "text": "FormChangesProps" + } + ], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [], + "returnComment": [], + "initialIsOpen": false + } + ], + "interfaces": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormChangesProps", + "type": "Interface", + "tags": [], + "label": "FormChangesProps", + "description": [], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormChangesProps.count", + "type": "number", + "tags": [], + "label": "count", + "description": [ + "\nNumber of fields rendered on the page that have changed." + ], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormChangesProps.report", + "type": "Function", + "tags": [], + "label": "report", + "description": [ + "\nCallback function used by a form field to indicate whether its current value is different to its initial value.\n" + ], + "signature": [ + "(isEqual: boolean) => ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.RevertFunction", + "text": "RevertFunction" + }, + " | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormChangesProps.report.$1", + "type": "boolean", + "tags": [], + "label": "isEqual", + "description": [], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false + } + ] + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormFieldProps", + "type": "Interface", + "tags": [], + "label": "FormFieldProps", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.FormFieldProps", + "text": "FormFieldProps" + }, + "<T>" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormFieldProps.as", + "type": "Uncategorized", + "tags": [], + "label": "as", + "description": [], + "signature": [ + "T | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormFieldProps.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormFieldProps.validate", + "type": "CompoundType", + "tags": [], + "label": "validate", + "description": [], + "signature": [ + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.ValidateOptions", + "text": "ValidateOptions" + }, + " | ", + "FieldValidator", + " | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormLabelProps", + "type": "Interface", + "tags": [], + "label": "FormLabelProps", + "description": [], + "path": "x-pack/packages/security/form_components/src/form_label.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormLabelProps.for", + "type": "string", + "tags": [], + "label": "for", + "description": [ + "\nName of target form field." + ], + "path": "x-pack/packages/security/form_components/src/form_label.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormRowProps", + "type": "Interface", + "tags": [], + "label": "FormRowProps", + "description": [], + "path": "x-pack/packages/security/form_components/src/form_row.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.FormRowProps.name", + "type": "string", + "tags": [], + "label": "name", + "description": [ + "\nOptional name of form field.\n\nIf not provided the name will be inferred from its child element." + ], + "signature": [ + "string | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_row.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ValidateOptions", + "type": "Interface", + "tags": [], + "label": "ValidateOptions", + "description": [], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ValidateOptions.required", + "type": "string", + "tags": [], + "label": "required", + "description": [], + "signature": [ + "string | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ValidateOptions.pattern", + "type": "Object", + "tags": [], + "label": "pattern", + "description": [], + "signature": [ + "{ value: RegExp; message: string; } | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ValidateOptions.minLength", + "type": "Object", + "tags": [], + "label": "minLength", + "description": [], + "signature": [ + "{ value: number; message: string; } | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ValidateOptions.maxLength", + "type": "Object", + "tags": [], + "label": "maxLength", + "description": [], + "signature": [ + "{ value: number; message: string; } | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ValidateOptions.min", + "type": "Object", + "tags": [], + "label": "min", + "description": [], + "signature": [ + "{ value: number; message: string; } | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ValidateOptions.max", + "type": "Object", + "tags": [], + "label": "max", + "description": [], + "signature": [ + "{ value: number; message: string; } | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_field.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + } + ], + "enums": [], + "misc": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ReportFunction", + "type": "Type", + "tags": [], + "label": "ReportFunction", + "description": [], + "signature": [ + "(isEqual: boolean) => ", + { + "pluginId": "@kbn/security-form-components", + "scope": "common", + "docId": "kibKbnSecurityFormComponentsPluginApi", + "section": "def-common.RevertFunction", + "text": "RevertFunction" + }, + " | undefined" + ], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [ + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.ReportFunction.$1", + "type": "boolean", + "tags": [], + "label": "isEqual", + "description": [], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-form-components", + "id": "def-common.RevertFunction", + "type": "Type", + "tags": [], + "label": "RevertFunction", + "description": [], + "signature": [ + "() => void" + ], + "path": "x-pack/packages/security/form_components/src/form_changes.tsx", + "deprecated": false, + "trackAdoption": false, + "returnComment": [], + "children": [], + "initialIsOpen": false + } + ], + "objects": [] + } +} \ No newline at end of file diff --git a/api_docs/kbn_security_form_components.mdx b/api_docs/kbn_security_form_components.mdx new file mode 100644 index 0000000000000..069c8ec98164f --- /dev/null +++ b/api_docs/kbn_security_form_components.mdx @@ -0,0 +1,36 @@ +--- +#### +#### This document is auto-generated and is meant to be viewed inside our experimental, new docs system. +#### Reach out in #docs-engineering for more info. +#### +id: kibKbnSecurityFormComponentsPluginApi +slug: /kibana-dev-docs/api/kbn-security-form-components +title: "@kbn/security-form-components" +image: https://source.unsplash.com/400x175/?github +description: API docs for the @kbn/security-form-components plugin +date: 2024-06-26 +tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-form-components'] +--- +import kbnSecurityFormComponentsObj from './kbn_security_form_components.devdocs.json'; + + + +Contact [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) for questions regarding this plugin. + +**Code health stats** + +| Public API count | Any count | Items lacking comments | Missing exports | +|-------------------|-----------|------------------------|-----------------| +| 35 | 0 | 25 | 0 | + +## Common + +### Functions +<DocDefinitionList data={kbnSecurityFormComponentsObj.common.functions}/> + +### Interfaces +<DocDefinitionList data={kbnSecurityFormComponentsObj.common.interfaces}/> + +### Consts, variables and types +<DocDefinitionList data={kbnSecurityFormComponentsObj.common.misc}/> + diff --git a/api_docs/kbn_security_hardening.mdx b/api_docs/kbn_security_hardening.mdx index 98ebbb51f5c28..94c8ff264b9ee 100644 --- a/api_docs/kbn_security_hardening.mdx +++ b/api_docs/kbn_security_hardening.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-hardening title: "@kbn/security-hardening" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-hardening plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-hardening'] --- import kbnSecurityHardeningObj from './kbn_security_hardening.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_common.devdocs.json b/api_docs/kbn_security_plugin_types_common.devdocs.json index 804df8e1e3d13..4bb4d0397c70f 100644 --- a/api_docs/kbn_security_plugin_types_common.devdocs.json +++ b/api_docs/kbn_security_plugin_types_common.devdocs.json @@ -20,6 +20,119 @@ "classes": [], "functions": [], "interfaces": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyAggregations", + "type": "Interface", + "tags": [], + "label": "ApiKeyAggregations", + "description": [], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyAggregations.usernames", + "type": "Object", + "tags": [], + "label": "usernames", + "description": [], + "signature": [ + "AggregationsStringTermsAggregate", + " | undefined" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyAggregations.types", + "type": "Object", + "tags": [], + "label": "types", + "description": [], + "signature": [ + "AggregationsStringTermsAggregate", + " | undefined" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyAggregations.expired", + "type": "Object", + "tags": [], + "label": "expired", + "description": [], + "signature": [ + "AggregationsFilterAggregateKeys", + " | undefined" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyAggregations.managed", + "type": "Object", + "tags": [], + "label": "managed", + "description": [], + "signature": [ + "{ buckets: { metadataBased: ", + "AggregationsFilterAggregateKeys", + "; namePrefixBased: ", + "AggregationsFilterAggregateKeys", + "; }; } | undefined" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyToInvalidate", + "type": "Interface", + "tags": [], + "label": "ApiKeyToInvalidate", + "description": [], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyToInvalidate.id", + "type": "string", + "tags": [], + "label": "id", + "description": [], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyToInvalidate.name", + "type": "string", + "tags": [], + "label": "name", + "description": [], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-plugin-types-common", "id": "def-common.AuthenticatedUser", @@ -203,6 +316,211 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.BaseApiKey", + "type": "Interface", + "tags": [], + "label": "BaseApiKey", + "description": [ + "\nFixing up `estypes.SecurityApiKey` type since some fields are marked as optional even though they are guaranteed to be returned.\n\nTODO: Remove this type when `@elastic/elasticsearch` has been updated." + ], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.BaseApiKey", + "text": "BaseApiKey" + }, + " extends ", + "SecurityApiKey" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.BaseApiKey.username", + "type": "string", + "tags": [], + "label": "username", + "description": [], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.BaseApiKey.realm", + "type": "string", + "tags": [], + "label": "realm", + "description": [], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.BaseApiKey.creation", + "type": "number", + "tags": [], + "label": "creation", + "description": [], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.BaseApiKey.metadata", + "type": "Object", + "tags": [], + "label": "metadata", + "description": [], + "signature": [ + "{ [x: string]: any; }" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.BaseApiKey.role_descriptors", + "type": "Object", + "tags": [], + "label": "role_descriptors", + "description": [], + "signature": [ + "{ [x: string]: ", + "SecurityRoleDescriptor", + "; }" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.CrossClusterApiKey", + "type": "Interface", + "tags": [], + "label": "CrossClusterApiKey", + "description": [ + "\nInterface representing a cross-cluster API key the way it is returned by Elasticsearch GET endpoint.\n\nTODO: Remove this type when `@elastic/elasticsearch` has been updated." + ], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.CrossClusterApiKey", + "text": "CrossClusterApiKey" + }, + " extends ", + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.BaseApiKey", + "text": "BaseApiKey" + } + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.CrossClusterApiKey.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"cross_cluster\"" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.CrossClusterApiKey.access", + "type": "Object", + "tags": [], + "label": "access", + "description": [ + "\nThe access to be granted to this API key. The access is composed of permissions for cross-cluster\nsearch and cross-cluster replication. At least one of them must be specified." + ], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.CrossClusterApiKeyAccess", + "text": "CrossClusterApiKeyAccess" + } + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.CrossClusterApiKeyAccess", + "type": "Interface", + "tags": [], + "label": "CrossClusterApiKeyAccess", + "description": [], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.CrossClusterApiKeyAccess.search", + "type": "Array", + "tags": [], + "label": "search", + "description": [ + "\nA list of indices permission entries for cross-cluster search." + ], + "signature": [ + "CrossClusterApiKeySearch[] | undefined" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.CrossClusterApiKeyAccess.replication", + "type": "Array", + "tags": [], + "label": "replication", + "description": [ + "\nA list of indices permission entries for cross-cluster replication." + ], + "signature": [ + "CrossClusterApiKeyReplication[] | undefined" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-plugin-types-common", "id": "def-common.FeaturesPrivileges", @@ -231,6 +549,100 @@ ], "initialIsOpen": false }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ManagedApiKey", + "type": "Interface", + "tags": [], + "label": "ManagedApiKey", + "description": [ + "\nInterface representing a REST API key that is managed by Kibana." + ], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.ManagedApiKey", + "text": "ManagedApiKey" + }, + " extends ", + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.BaseApiKey", + "text": "BaseApiKey" + } + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ManagedApiKey.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"managed\"" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.RestApiKey", + "type": "Interface", + "tags": [], + "label": "RestApiKey", + "description": [ + "\nInterface representing a REST API key the way it is returned by Elasticsearch GET endpoint.\n\nTODO: Remove this type when `@elastic/elasticsearch` has been updated." + ], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.RestApiKey", + "text": "RestApiKey" + }, + " extends ", + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.BaseApiKey", + "text": "BaseApiKey" + } + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.RestApiKey.type", + "type": "string", + "tags": [], + "label": "type", + "description": [], + "signature": [ + "\"rest\"" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false + } + ], + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-plugin-types-common", "id": "def-common.Role", @@ -1406,6 +1818,87 @@ ], "enums": [], "misc": [ + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKey", + "type": "Type", + "tags": [], + "label": "ApiKey", + "description": [ + "\nInterface representing an API key the way it is returned by Elasticsearch GET endpoint." + ], + "signature": [ + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.RestApiKey", + "text": "RestApiKey" + }, + " | ", + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.CrossClusterApiKey", + "text": "CrossClusterApiKey" + } + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.ApiKeyRoleDescriptors", + "type": "Type", + "tags": [], + "label": "ApiKeyRoleDescriptors", + "description": [], + "signature": [ + "{ [x: string]: ", + "SecurityRoleDescriptor", + "; }" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.CategorizedApiKey", + "type": "Type", + "tags": [], + "label": "CategorizedApiKey", + "description": [ + "\nInterface representing an API key the way it is presented in the Kibana UI (with Kibana system\nAPI keys given its own dedicated `managed` type)." + ], + "signature": [ + "(", + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.ApiKey", + "text": "ApiKey" + }, + " | ", + { + "pluginId": "@kbn/security-plugin-types-common", + "scope": "common", + "docId": "kibKbnSecurityPluginTypesCommonPluginApi", + "section": "def-common.ManagedApiKey", + "text": "ManagedApiKey" + }, + ") & { expired: boolean; }" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-plugin-types-common", "id": "def-common.LoginLayout", @@ -1423,6 +1916,23 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/security-plugin-types-common", + "id": "def-common.QueryApiKeyResult", + "type": "Type", + "tags": [], + "label": "QueryApiKeyResult", + "description": [ + "\nResponse of Kibana Query API keys endpoint." + ], + "signature": [ + "SuccessQueryApiKeyResult | ErrorQueryApiKeyResult" + ], + "path": "x-pack/packages/security/plugin_types_common/src/api_keys/api_key.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-plugin-types-common", "id": "def-common.UserProfileData", diff --git a/api_docs/kbn_security_plugin_types_common.mdx b/api_docs/kbn_security_plugin_types_common.mdx index 8716850ec1ae5..f52bcd45549a1 100644 --- a/api_docs/kbn_security_plugin_types_common.mdx +++ b/api_docs/kbn_security_plugin_types_common.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-common title: "@kbn/security-plugin-types-common" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-common plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-common'] --- import kbnSecurityPluginTypesCommonObj from './kbn_security_plugin_types_common.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana- | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 88 | 0 | 40 | 0 | +| 116 | 0 | 58 | 0 | ## Common diff --git a/api_docs/kbn_security_plugin_types_public.devdocs.json b/api_docs/kbn_security_plugin_types_public.devdocs.json index 637e988957f0e..b2c795162fd9a 100644 --- a/api_docs/kbn_security_plugin_types_public.devdocs.json +++ b/api_docs/kbn_security_plugin_types_public.devdocs.json @@ -520,14 +520,6 @@ { "plugin": "security", "path": "x-pack/plugins/security/public/plugin.tsx" - }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx" - }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" } ] }, @@ -643,10 +635,6 @@ "plugin": "security", "path": "x-pack/plugins/security/public/plugin.tsx" }, - { - "plugin": "maps", - "path": "x-pack/plugins/maps/public/classes/sources/es_search_source/es_search_source.tsx" - }, { "plugin": "imageEmbeddable", "path": "src/plugins/image_embeddable/public/components/image_editor/open_image_editor.tsx" diff --git a/api_docs/kbn_security_plugin_types_public.mdx b/api_docs/kbn_security_plugin_types_public.mdx index 9e043c059ade2..023f5ccf04054 100644 --- a/api_docs/kbn_security_plugin_types_public.mdx +++ b/api_docs/kbn_security_plugin_types_public.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-public title: "@kbn/security-plugin-types-public" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-public plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-public'] --- import kbnSecurityPluginTypesPublicObj from './kbn_security_plugin_types_public.devdocs.json'; diff --git a/api_docs/kbn_security_plugin_types_server.devdocs.json b/api_docs/kbn_security_plugin_types_server.devdocs.json index 66a58ecffebd0..03c206b69bd4e 100644 --- a/api_docs/kbn_security_plugin_types_server.devdocs.json +++ b/api_docs/kbn_security_plugin_types_server.devdocs.json @@ -134,6 +134,95 @@ ], "returnComment": [], "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.getUpdateRestApiKeyWithKibanaPrivilegesSchema", + "type": "Function", + "tags": [], + "label": "getUpdateRestApiKeyWithKibanaPrivilegesSchema", + "description": [], + "signature": [ + "(getBasePrivilegeNames: () => { global: string[]; space: string[]; }) => ExtendedObjectType<{ type: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<\"rest\" | undefined>; name: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string>; expiration: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string | undefined>; role_descriptors: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Record<string, Readonly<{} & {}>>>; metadata: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Readonly<{} & {}> | undefined>; }, { role_descriptors: null; name: null; id: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string>; kibana_role_descriptors: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Record<string, Readonly<{} & { kibana: Readonly<{ base?: string[] | undefined; feature?: Record<string, string[]> | undefined; } & { spaces: string[] | \"*\"[]; }>[]; elasticsearch: Readonly<{ cluster?: string[] | undefined; indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; }>[] | undefined; remote_cluster?: Readonly<{} & { privileges: string[]; clusters: string[]; }>[] | undefined; remote_indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; clusters: string[]; }>[] | undefined; run_as?: string[] | undefined; } & {}>; }>>>; }>" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "children": [ + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.getUpdateRestApiKeyWithKibanaPrivilegesSchema.$1", + "type": "Function", + "tags": [], + "label": "getBasePrivilegeNames", + "description": [], + "signature": [ + "() => { global: string[]; space: string[]; }" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "isRequired": true + } + ], + "returnComment": [], + "initialIsOpen": false } ], "interfaces": [ @@ -4366,6 +4455,85 @@ "trackAdoption": false, "initialIsOpen": false }, + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.UpdateAPIKeyParams", + "type": "Type", + "tags": [], + "label": "UpdateAPIKeyParams", + "description": [ + "\nRequest body of Kibana Update API key endpoint." + ], + "signature": [ + "Readonly<{ type?: \"rest\" | undefined; metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { id: string; role_descriptors: Record<string, Readonly<{} & {}>>; }> | Readonly<{ metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { id: string; type: \"cross_cluster\"; access: Readonly<{ search?: Readonly<{ query?: any; field_security?: any; allow_restricted_indices?: boolean | undefined; } & { names: string[]; }>[] | undefined; replication?: Readonly<{} & { names: string[]; }>[] | undefined; } & {}>; }> | Readonly<{ type?: \"rest\" | undefined; metadata?: Readonly<{} & {}> | undefined; expiration?: string | undefined; } & { id: string; kibana_role_descriptors: Record<string, Readonly<{} & { kibana: Readonly<{ base?: string[] | undefined; feature?: Record<string, string[]> | undefined; } & { spaces: string[] | \"*\"[]; }>[]; elasticsearch: Readonly<{ cluster?: string[] | undefined; indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; }>[] | undefined; remote_cluster?: Readonly<{} & { privileges: string[]; clusters: string[]; }>[] | undefined; remote_indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; clusters: string[]; }>[] | undefined; run_as?: string[] | undefined; } & {}>; }>>; }>" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.UpdateAPIKeyResult", + "type": "Type", + "tags": [], + "label": "UpdateAPIKeyResult", + "description": [ + "\nResponse of Kibana Update API key endpoint." + ], + "signature": [ + "SecurityUpdateApiKeyResponse" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.UpdateCrossClusterAPIKeyParams", + "type": "Type", + "tags": [], + "label": "UpdateCrossClusterAPIKeyParams", + "description": [], + "signature": [ + "{ readonly metadata?: Readonly<{} & {}> | undefined; readonly expiration?: string | undefined; readonly id: string; readonly type: \"cross_cluster\"; readonly access: Readonly<{ search?: Readonly<{ query?: any; field_security?: any; allow_restricted_indices?: boolean | undefined; } & { names: string[]; }>[] | undefined; replication?: Readonly<{} & { names: string[]; }>[] | undefined; } & {}>; }" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.UpdateRestAPIKeyParams", + "type": "Type", + "tags": [], + "label": "UpdateRestAPIKeyParams", + "description": [], + "signature": [ + "{ readonly type?: \"rest\" | undefined; readonly metadata?: Readonly<{} & {}> | undefined; readonly expiration?: string | undefined; readonly id: string; readonly role_descriptors: Record<string, Readonly<{} & {}>>; }" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.UpdateRestAPIKeyWithKibanaPrivilegesParams", + "type": "Type", + "tags": [], + "label": "UpdateRestAPIKeyWithKibanaPrivilegesParams", + "description": [], + "signature": [ + "{ readonly type?: \"rest\" | undefined; readonly metadata?: Readonly<{} & {}> | undefined; readonly expiration?: string | undefined; readonly id: string; readonly kibana_role_descriptors: Record<string, Readonly<{} & { kibana: Readonly<{ base?: string[] | undefined; feature?: Record<string, string[]> | undefined; } & { spaces: string[] | \"*\"[]; }>[]; elasticsearch: Readonly<{ cluster?: string[] | undefined; indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; }>[] | undefined; remote_cluster?: Readonly<{} & { privileges: string[]; clusters: string[]; }>[] | undefined; remote_indices?: Readonly<{ query?: string | undefined; field_security?: Record<\"except\" | \"grant\", string[]> | undefined; allow_restricted_indices?: boolean | undefined; } & { names: string[]; privileges: string[]; clusters: string[]; }>[] | undefined; run_as?: string[] | undefined; } & {}>; }>>; }" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, { "parentPluginId": "@kbn/security-plugin-types-server", "id": "def-server.UserProfileServiceStart", @@ -4610,6 +4778,178 @@ "deprecated": false, "trackAdoption": false, "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.updateCrossClusterApiKeySchema", + "type": "Object", + "tags": [], + "label": "updateCrossClusterApiKeySchema", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<ExtendedProps<ExtendedProps<{ type: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<\"rest\" | undefined>; name: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string>; expiration: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string | undefined>; role_descriptors: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Record<string, Readonly<{} & {}>>>; metadata: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Readonly<{} & {}> | undefined>; }, { type: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<\"cross_cluster\">; role_descriptors: null; access: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<{ search: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Readonly<{ query?: any; field_security?: any; allow_restricted_indices?: boolean | undefined; } & { names: string[]; }>[] | undefined>; replication: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Readonly<{} & { names: string[]; }>[] | undefined>; }>; }>, { name: null; id: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string>; }>>" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false + }, + { + "parentPluginId": "@kbn/security-plugin-types-server", + "id": "def-server.updateRestApiKeySchema", + "type": "Object", + "tags": [], + "label": "updateRestApiKeySchema", + "description": [], + "signature": [ + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.ObjectType", + "text": "ObjectType" + }, + "<ExtendedProps<{ type: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<\"rest\" | undefined>; name: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string>; expiration: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string | undefined>; role_descriptors: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Record<string, Readonly<{} & {}>>>; metadata: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<Readonly<{} & {}> | undefined>; }, { name: null; id: ", + { + "pluginId": "@kbn/config-schema", + "scope": "common", + "docId": "kibKbnConfigSchemaPluginApi", + "section": "def-common.Type", + "text": "Type" + }, + "<string>; }>>" + ], + "path": "x-pack/packages/security/plugin_types_server/src/authentication/api_keys/api_keys.ts", + "deprecated": false, + "trackAdoption": false, + "initialIsOpen": false } ] }, diff --git a/api_docs/kbn_security_plugin_types_server.mdx b/api_docs/kbn_security_plugin_types_server.mdx index 4f40616338e17..d2033e6e7c0d0 100644 --- a/api_docs/kbn_security_plugin_types_server.mdx +++ b/api_docs/kbn_security_plugin_types_server.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-plugin-types-server title: "@kbn/security-plugin-types-server" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-plugin-types-server plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-plugin-types-server'] --- import kbnSecurityPluginTypesServerObj from './kbn_security_plugin_types_server.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana- | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 207 | 0 | 114 | 0 | +| 216 | 0 | 121 | 0 | ## Server diff --git a/api_docs/kbn_security_solution_features.mdx b/api_docs/kbn_security_solution_features.mdx index 11d01e2283f6e..41cb83896aaf1 100644 --- a/api_docs/kbn_security_solution_features.mdx +++ b/api_docs/kbn_security_solution_features.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-features title: "@kbn/security-solution-features" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-features plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-features'] --- import kbnSecuritySolutionFeaturesObj from './kbn_security_solution_features.devdocs.json'; diff --git a/api_docs/kbn_security_solution_navigation.mdx b/api_docs/kbn_security_solution_navigation.mdx index eb95c41e1a7cd..2de0e8ae55c3d 100644 --- a/api_docs/kbn_security_solution_navigation.mdx +++ b/api_docs/kbn_security_solution_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-navigation title: "@kbn/security-solution-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-navigation plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-navigation'] --- import kbnSecuritySolutionNavigationObj from './kbn_security_solution_navigation.devdocs.json'; diff --git a/api_docs/kbn_security_solution_side_nav.mdx b/api_docs/kbn_security_solution_side_nav.mdx index 5b421d98cb3ed..2e76c2aff92dc 100644 --- a/api_docs/kbn_security_solution_side_nav.mdx +++ b/api_docs/kbn_security_solution_side_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-side-nav title: "@kbn/security-solution-side-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-side-nav plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-side-nav'] --- import kbnSecuritySolutionSideNavObj from './kbn_security_solution_side_nav.devdocs.json'; diff --git a/api_docs/kbn_security_solution_storybook_config.mdx b/api_docs/kbn_security_solution_storybook_config.mdx index 3b52d5f3d4c8a..65ef8db957321 100644 --- a/api_docs/kbn_security_solution_storybook_config.mdx +++ b/api_docs/kbn_security_solution_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-security-solution-storybook-config title: "@kbn/security-solution-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/security-solution-storybook-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/security-solution-storybook-config'] --- import kbnSecuritySolutionStorybookConfigObj from './kbn_security_solution_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_autocomplete.mdx b/api_docs/kbn_securitysolution_autocomplete.mdx index e50848a01023e..6de17c19ff30b 100644 --- a/api_docs/kbn_securitysolution_autocomplete.mdx +++ b/api_docs/kbn_securitysolution_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-autocomplete title: "@kbn/securitysolution-autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-autocomplete plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-autocomplete'] --- import kbnSecuritysolutionAutocompleteObj from './kbn_securitysolution_autocomplete.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_data_table.mdx b/api_docs/kbn_securitysolution_data_table.mdx index 0059ce92bdb49..afa75b2237c23 100644 --- a/api_docs/kbn_securitysolution_data_table.mdx +++ b/api_docs/kbn_securitysolution_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-data-table title: "@kbn/securitysolution-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-data-table plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-data-table'] --- import kbnSecuritysolutionDataTableObj from './kbn_securitysolution_data_table.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_ecs.mdx b/api_docs/kbn_securitysolution_ecs.mdx index b14d4fe5eabb1..db86cf7fdf951 100644 --- a/api_docs/kbn_securitysolution_ecs.mdx +++ b/api_docs/kbn_securitysolution_ecs.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-ecs title: "@kbn/securitysolution-ecs" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-ecs plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-ecs'] --- import kbnSecuritysolutionEcsObj from './kbn_securitysolution_ecs.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_es_utils.mdx b/api_docs/kbn_securitysolution_es_utils.mdx index 19ff4819ebad9..569d781cf33fc 100644 --- a/api_docs/kbn_securitysolution_es_utils.mdx +++ b/api_docs/kbn_securitysolution_es_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-es-utils title: "@kbn/securitysolution-es-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-es-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-es-utils'] --- import kbnSecuritysolutionEsUtilsObj from './kbn_securitysolution_es_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_exception_list_components.mdx b/api_docs/kbn_securitysolution_exception_list_components.mdx index 540aac983e4aa..9b4d160a9557c 100644 --- a/api_docs/kbn_securitysolution_exception_list_components.mdx +++ b/api_docs/kbn_securitysolution_exception_list_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-exception-list-components title: "@kbn/securitysolution-exception-list-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-exception-list-components plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-exception-list-components'] --- import kbnSecuritysolutionExceptionListComponentsObj from './kbn_securitysolution_exception_list_components.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_hook_utils.mdx b/api_docs/kbn_securitysolution_hook_utils.mdx index cc0a347e7787d..dd8b416cb9302 100644 --- a/api_docs/kbn_securitysolution_hook_utils.mdx +++ b/api_docs/kbn_securitysolution_hook_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-hook-utils title: "@kbn/securitysolution-hook-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-hook-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-hook-utils'] --- import kbnSecuritysolutionHookUtilsObj from './kbn_securitysolution_hook_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx index ffb7a35800470..3832b2ee6431f 100644 --- a/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_alerting_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-alerting-types title: "@kbn/securitysolution-io-ts-alerting-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-alerting-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-alerting-types'] --- import kbnSecuritysolutionIoTsAlertingTypesObj from './kbn_securitysolution_io_ts_alerting_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_list_types.mdx b/api_docs/kbn_securitysolution_io_ts_list_types.mdx index 47d54988e60ae..53f92776db7fd 100644 --- a/api_docs/kbn_securitysolution_io_ts_list_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_list_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-list-types title: "@kbn/securitysolution-io-ts-list-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-list-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-list-types'] --- import kbnSecuritysolutionIoTsListTypesObj from './kbn_securitysolution_io_ts_list_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_types.mdx b/api_docs/kbn_securitysolution_io_ts_types.mdx index 28c6010f5c90e..caa5305ea96dc 100644 --- a/api_docs/kbn_securitysolution_io_ts_types.mdx +++ b/api_docs/kbn_securitysolution_io_ts_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-types title: "@kbn/securitysolution-io-ts-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-types'] --- import kbnSecuritysolutionIoTsTypesObj from './kbn_securitysolution_io_ts_types.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_io_ts_utils.mdx b/api_docs/kbn_securitysolution_io_ts_utils.mdx index b8d580394a2c6..2688f49d4073f 100644 --- a/api_docs/kbn_securitysolution_io_ts_utils.mdx +++ b/api_docs/kbn_securitysolution_io_ts_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-io-ts-utils title: "@kbn/securitysolution-io-ts-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-io-ts-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-io-ts-utils'] --- import kbnSecuritysolutionIoTsUtilsObj from './kbn_securitysolution_io_ts_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_api.mdx b/api_docs/kbn_securitysolution_list_api.mdx index ef9d50bfa1190..ef49bb77a112c 100644 --- a/api_docs/kbn_securitysolution_list_api.mdx +++ b/api_docs/kbn_securitysolution_list_api.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-api title: "@kbn/securitysolution-list-api" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-api plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-api'] --- import kbnSecuritysolutionListApiObj from './kbn_securitysolution_list_api.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_constants.mdx b/api_docs/kbn_securitysolution_list_constants.mdx index 984ecefb93db8..51ac7621c6973 100644 --- a/api_docs/kbn_securitysolution_list_constants.mdx +++ b/api_docs/kbn_securitysolution_list_constants.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-constants title: "@kbn/securitysolution-list-constants" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-constants plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-constants'] --- import kbnSecuritysolutionListConstantsObj from './kbn_securitysolution_list_constants.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_hooks.mdx b/api_docs/kbn_securitysolution_list_hooks.mdx index 818af5e18bcdc..6ef501e51cbe3 100644 --- a/api_docs/kbn_securitysolution_list_hooks.mdx +++ b/api_docs/kbn_securitysolution_list_hooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-hooks title: "@kbn/securitysolution-list-hooks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-hooks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-hooks'] --- import kbnSecuritysolutionListHooksObj from './kbn_securitysolution_list_hooks.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_list_utils.mdx b/api_docs/kbn_securitysolution_list_utils.mdx index 7c06fc862b4c7..da55f5194e003 100644 --- a/api_docs/kbn_securitysolution_list_utils.mdx +++ b/api_docs/kbn_securitysolution_list_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-list-utils title: "@kbn/securitysolution-list-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-list-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-list-utils'] --- import kbnSecuritysolutionListUtilsObj from './kbn_securitysolution_list_utils.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_rules.mdx b/api_docs/kbn_securitysolution_rules.mdx index 695e4d263ae59..dedb606412550 100644 --- a/api_docs/kbn_securitysolution_rules.mdx +++ b/api_docs/kbn_securitysolution_rules.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-rules title: "@kbn/securitysolution-rules" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-rules plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-rules'] --- import kbnSecuritysolutionRulesObj from './kbn_securitysolution_rules.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_t_grid.mdx b/api_docs/kbn_securitysolution_t_grid.mdx index c14772cae9b97..eed19f2fe3bf8 100644 --- a/api_docs/kbn_securitysolution_t_grid.mdx +++ b/api_docs/kbn_securitysolution_t_grid.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-t-grid title: "@kbn/securitysolution-t-grid" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-t-grid plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-t-grid'] --- import kbnSecuritysolutionTGridObj from './kbn_securitysolution_t_grid.devdocs.json'; diff --git a/api_docs/kbn_securitysolution_utils.mdx b/api_docs/kbn_securitysolution_utils.mdx index dc8ffc2e93980..d02e537595714 100644 --- a/api_docs/kbn_securitysolution_utils.mdx +++ b/api_docs/kbn_securitysolution_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-securitysolution-utils title: "@kbn/securitysolution-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/securitysolution-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/securitysolution-utils'] --- import kbnSecuritysolutionUtilsObj from './kbn_securitysolution_utils.devdocs.json'; diff --git a/api_docs/kbn_server_http_tools.mdx b/api_docs/kbn_server_http_tools.mdx index 7c4a7456e0c97..1481089a65dc9 100644 --- a/api_docs/kbn_server_http_tools.mdx +++ b/api_docs/kbn_server_http_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-http-tools title: "@kbn/server-http-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-http-tools plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-http-tools'] --- import kbnServerHttpToolsObj from './kbn_server_http_tools.devdocs.json'; diff --git a/api_docs/kbn_server_route_repository.mdx b/api_docs/kbn_server_route_repository.mdx index aede21299ca77..aec55c90ab1e8 100644 --- a/api_docs/kbn_server_route_repository.mdx +++ b/api_docs/kbn_server_route_repository.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-server-route-repository title: "@kbn/server-route-repository" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/server-route-repository plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/server-route-repository'] --- import kbnServerRouteRepositoryObj from './kbn_server_route_repository.devdocs.json'; diff --git a/api_docs/kbn_serverless_common_settings.mdx b/api_docs/kbn_serverless_common_settings.mdx index afbb242cadba7..5354734905af9 100644 --- a/api_docs/kbn_serverless_common_settings.mdx +++ b/api_docs/kbn_serverless_common_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-common-settings title: "@kbn/serverless-common-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-common-settings plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-common-settings'] --- import kbnServerlessCommonSettingsObj from './kbn_serverless_common_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_observability_settings.mdx b/api_docs/kbn_serverless_observability_settings.mdx index 4cfd9c000aac5..5c74bfb9e7d5c 100644 --- a/api_docs/kbn_serverless_observability_settings.mdx +++ b/api_docs/kbn_serverless_observability_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-observability-settings title: "@kbn/serverless-observability-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-observability-settings plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-observability-settings'] --- import kbnServerlessObservabilitySettingsObj from './kbn_serverless_observability_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_project_switcher.mdx b/api_docs/kbn_serverless_project_switcher.mdx index fc656a8ab2dba..a7f14429a85a3 100644 --- a/api_docs/kbn_serverless_project_switcher.mdx +++ b/api_docs/kbn_serverless_project_switcher.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-project-switcher title: "@kbn/serverless-project-switcher" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-project-switcher plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-project-switcher'] --- import kbnServerlessProjectSwitcherObj from './kbn_serverless_project_switcher.devdocs.json'; diff --git a/api_docs/kbn_serverless_search_settings.mdx b/api_docs/kbn_serverless_search_settings.mdx index 0b0076552bb9f..e407d28bede69 100644 --- a/api_docs/kbn_serverless_search_settings.mdx +++ b/api_docs/kbn_serverless_search_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-search-settings title: "@kbn/serverless-search-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-search-settings plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-search-settings'] --- import kbnServerlessSearchSettingsObj from './kbn_serverless_search_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_security_settings.mdx b/api_docs/kbn_serverless_security_settings.mdx index 336ffbf1a690f..95da157646e69 100644 --- a/api_docs/kbn_serverless_security_settings.mdx +++ b/api_docs/kbn_serverless_security_settings.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-security-settings title: "@kbn/serverless-security-settings" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-security-settings plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-security-settings'] --- import kbnServerlessSecuritySettingsObj from './kbn_serverless_security_settings.devdocs.json'; diff --git a/api_docs/kbn_serverless_storybook_config.mdx b/api_docs/kbn_serverless_storybook_config.mdx index fa922ec7f2c27..80c996ea69f9d 100644 --- a/api_docs/kbn_serverless_storybook_config.mdx +++ b/api_docs/kbn_serverless_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-serverless-storybook-config title: "@kbn/serverless-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/serverless-storybook-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/serverless-storybook-config'] --- import kbnServerlessStorybookConfigObj from './kbn_serverless_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_svg.mdx b/api_docs/kbn_shared_svg.mdx index f13fb766566f2..3504df630e54f 100644 --- a/api_docs/kbn_shared_svg.mdx +++ b/api_docs/kbn_shared_svg.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-svg title: "@kbn/shared-svg" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-svg plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-svg'] --- import kbnSharedSvgObj from './kbn_shared_svg.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_avatar_solution.mdx b/api_docs/kbn_shared_ux_avatar_solution.mdx index 08d323e5c6eb7..e124911c42941 100644 --- a/api_docs/kbn_shared_ux_avatar_solution.mdx +++ b/api_docs/kbn_shared_ux_avatar_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-avatar-solution title: "@kbn/shared-ux-avatar-solution" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-avatar-solution plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-avatar-solution'] --- import kbnSharedUxAvatarSolutionObj from './kbn_shared_ux_avatar_solution.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx index 868b6f92dfac9..d245a6763c95b 100644 --- a/api_docs/kbn_shared_ux_button_exit_full_screen.mdx +++ b/api_docs/kbn_shared_ux_button_exit_full_screen.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-exit-full-screen title: "@kbn/shared-ux-button-exit-full-screen" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-exit-full-screen plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-exit-full-screen'] --- import kbnSharedUxButtonExitFullScreenObj from './kbn_shared_ux_button_exit_full_screen.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_button_toolbar.mdx b/api_docs/kbn_shared_ux_button_toolbar.mdx index d2146b12a0eac..eaf21527eb799 100644 --- a/api_docs/kbn_shared_ux_button_toolbar.mdx +++ b/api_docs/kbn_shared_ux_button_toolbar.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-button-toolbar title: "@kbn/shared-ux-button-toolbar" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-button-toolbar plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-button-toolbar'] --- import kbnSharedUxButtonToolbarObj from './kbn_shared_ux_button_toolbar.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data.mdx b/api_docs/kbn_shared_ux_card_no_data.mdx index e05573e50abf7..76d564629a2f7 100644 --- a/api_docs/kbn_shared_ux_card_no_data.mdx +++ b/api_docs/kbn_shared_ux_card_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data title: "@kbn/shared-ux-card-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data'] --- import kbnSharedUxCardNoDataObj from './kbn_shared_ux_card_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx index 50f1b823c5f4c..420d60ae2155f 100644 --- a/api_docs/kbn_shared_ux_card_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_card_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-card-no-data-mocks title: "@kbn/shared-ux-card-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-card-no-data-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-card-no-data-mocks'] --- import kbnSharedUxCardNoDataMocksObj from './kbn_shared_ux_card_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_chrome_navigation.mdx b/api_docs/kbn_shared_ux_chrome_navigation.mdx index fc56699729272..8ceb4841a3242 100644 --- a/api_docs/kbn_shared_ux_chrome_navigation.mdx +++ b/api_docs/kbn_shared_ux_chrome_navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-chrome-navigation title: "@kbn/shared-ux-chrome-navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-chrome-navigation plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-chrome-navigation'] --- import kbnSharedUxChromeNavigationObj from './kbn_shared_ux_chrome_navigation.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_error_boundary.mdx b/api_docs/kbn_shared_ux_error_boundary.mdx index d85ed952cb411..527e9298b20f2 100644 --- a/api_docs/kbn_shared_ux_error_boundary.mdx +++ b/api_docs/kbn_shared_ux_error_boundary.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-error-boundary title: "@kbn/shared-ux-error-boundary" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-error-boundary plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-error-boundary'] --- import kbnSharedUxErrorBoundaryObj from './kbn_shared_ux_error_boundary.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_context.mdx b/api_docs/kbn_shared_ux_file_context.mdx index 56df21146cb5a..7b8c2eb6cc3a7 100644 --- a/api_docs/kbn_shared_ux_file_context.mdx +++ b/api_docs/kbn_shared_ux_file_context.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-context title: "@kbn/shared-ux-file-context" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-context plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-context'] --- import kbnSharedUxFileContextObj from './kbn_shared_ux_file_context.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image.mdx b/api_docs/kbn_shared_ux_file_image.mdx index d2947f2c24e7f..de929e1f2a27c 100644 --- a/api_docs/kbn_shared_ux_file_image.mdx +++ b/api_docs/kbn_shared_ux_file_image.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image title: "@kbn/shared-ux-file-image" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image'] --- import kbnSharedUxFileImageObj from './kbn_shared_ux_file_image.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_image_mocks.mdx b/api_docs/kbn_shared_ux_file_image_mocks.mdx index 8d020b9261da4..1096ad098dcfb 100644 --- a/api_docs/kbn_shared_ux_file_image_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_image_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-image-mocks title: "@kbn/shared-ux-file-image-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-image-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-image-mocks'] --- import kbnSharedUxFileImageMocksObj from './kbn_shared_ux_file_image_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_mocks.mdx b/api_docs/kbn_shared_ux_file_mocks.mdx index a6220a738a005..e6ec7f575da53 100644 --- a/api_docs/kbn_shared_ux_file_mocks.mdx +++ b/api_docs/kbn_shared_ux_file_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-mocks title: "@kbn/shared-ux-file-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-mocks'] --- import kbnSharedUxFileMocksObj from './kbn_shared_ux_file_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_picker.mdx b/api_docs/kbn_shared_ux_file_picker.mdx index 7489d95e2d4bb..d124be8945998 100644 --- a/api_docs/kbn_shared_ux_file_picker.mdx +++ b/api_docs/kbn_shared_ux_file_picker.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-picker title: "@kbn/shared-ux-file-picker" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-picker plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-picker'] --- import kbnSharedUxFilePickerObj from './kbn_shared_ux_file_picker.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_types.mdx b/api_docs/kbn_shared_ux_file_types.mdx index 994d34728f333..23f129275aee7 100644 --- a/api_docs/kbn_shared_ux_file_types.mdx +++ b/api_docs/kbn_shared_ux_file_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-types title: "@kbn/shared-ux-file-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-types'] --- import kbnSharedUxFileTypesObj from './kbn_shared_ux_file_types.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_upload.mdx b/api_docs/kbn_shared_ux_file_upload.mdx index e83be9a576b4a..8b435cfeeb9a9 100644 --- a/api_docs/kbn_shared_ux_file_upload.mdx +++ b/api_docs/kbn_shared_ux_file_upload.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-upload title: "@kbn/shared-ux-file-upload" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-upload plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-upload'] --- import kbnSharedUxFileUploadObj from './kbn_shared_ux_file_upload.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_file_util.mdx b/api_docs/kbn_shared_ux_file_util.mdx index 8489241db8f5c..0baaf9fa20c56 100644 --- a/api_docs/kbn_shared_ux_file_util.mdx +++ b/api_docs/kbn_shared_ux_file_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-file-util title: "@kbn/shared-ux-file-util" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-file-util plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-file-util'] --- import kbnSharedUxFileUtilObj from './kbn_shared_ux_file_util.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app.mdx b/api_docs/kbn_shared_ux_link_redirect_app.mdx index e700d15418e6e..b5f3e21df4ef6 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app title: "@kbn/shared-ux-link-redirect-app" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app'] --- import kbnSharedUxLinkRedirectAppObj from './kbn_shared_ux_link_redirect_app.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx index b4f29b76b5946..1f29f1423dfef 100644 --- a/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx +++ b/api_docs/kbn_shared_ux_link_redirect_app_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-link-redirect-app-mocks title: "@kbn/shared-ux-link-redirect-app-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-link-redirect-app-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-link-redirect-app-mocks'] --- import kbnSharedUxLinkRedirectAppMocksObj from './kbn_shared_ux_link_redirect_app_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown.mdx b/api_docs/kbn_shared_ux_markdown.mdx index 6dccb6fee5def..584710e8a7c87 100644 --- a/api_docs/kbn_shared_ux_markdown.mdx +++ b/api_docs/kbn_shared_ux_markdown.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown title: "@kbn/shared-ux-markdown" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown'] --- import kbnSharedUxMarkdownObj from './kbn_shared_ux_markdown.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_markdown_mocks.mdx b/api_docs/kbn_shared_ux_markdown_mocks.mdx index dfb28fcb0511f..d3026f1ce6e46 100644 --- a/api_docs/kbn_shared_ux_markdown_mocks.mdx +++ b/api_docs/kbn_shared_ux_markdown_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-markdown-mocks title: "@kbn/shared-ux-markdown-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-markdown-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-markdown-mocks'] --- import kbnSharedUxMarkdownMocksObj from './kbn_shared_ux_markdown_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx index c0c7436c0bde6..fac362d336dec 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data title: "@kbn/shared-ux-page-analytics-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data'] --- import kbnSharedUxPageAnalyticsNoDataObj from './kbn_shared_ux_page_analytics_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx index a7acd3a3b99d6..8faf41b2e7e37 100644 --- a/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_analytics_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-analytics-no-data-mocks title: "@kbn/shared-ux-page-analytics-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-analytics-no-data-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-analytics-no-data-mocks'] --- import kbnSharedUxPageAnalyticsNoDataMocksObj from './kbn_shared_ux_page_analytics_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx index 3971fb759e750..2986da6336b9c 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data title: "@kbn/shared-ux-page-kibana-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data'] --- import kbnSharedUxPageKibanaNoDataObj from './kbn_shared_ux_page_kibana_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx index 68200fa6aea97..8a3af9430f9f7 100644 --- a/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-no-data-mocks title: "@kbn/shared-ux-page-kibana-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-no-data-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-no-data-mocks'] --- import kbnSharedUxPageKibanaNoDataMocksObj from './kbn_shared_ux_page_kibana_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template.mdx b/api_docs/kbn_shared_ux_page_kibana_template.mdx index 0a4eefc59e001..93750f9e3781f 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template title: "@kbn/shared-ux-page-kibana-template" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template'] --- import kbnSharedUxPageKibanaTemplateObj from './kbn_shared_ux_page_kibana_template.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx index ccbd8bbf43463..8cb9ce911a4d4 100644 --- a/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_kibana_template_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-kibana-template-mocks title: "@kbn/shared-ux-page-kibana-template-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-kibana-template-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-kibana-template-mocks'] --- import kbnSharedUxPageKibanaTemplateMocksObj from './kbn_shared_ux_page_kibana_template_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data.mdx b/api_docs/kbn_shared_ux_page_no_data.mdx index fee653962b340..d6abe818bea3a 100644 --- a/api_docs/kbn_shared_ux_page_no_data.mdx +++ b/api_docs/kbn_shared_ux_page_no_data.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data title: "@kbn/shared-ux-page-no-data" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data'] --- import kbnSharedUxPageNoDataObj from './kbn_shared_ux_page_no_data.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config.mdx b/api_docs/kbn_shared_ux_page_no_data_config.mdx index e13fcb41c564e..feebd69ae5b07 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config title: "@kbn/shared-ux-page-no-data-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config'] --- import kbnSharedUxPageNoDataConfigObj from './kbn_shared_ux_page_no_data_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx index 3d948c3ea6d50..ba18cc14147e6 100644 --- a/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_config_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-config-mocks title: "@kbn/shared-ux-page-no-data-config-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-config-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-config-mocks'] --- import kbnSharedUxPageNoDataConfigMocksObj from './kbn_shared_ux_page_no_data_config_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx index fe23d1c64a041..af38374e3e772 100644 --- a/api_docs/kbn_shared_ux_page_no_data_mocks.mdx +++ b/api_docs/kbn_shared_ux_page_no_data_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-no-data-mocks title: "@kbn/shared-ux-page-no-data-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-no-data-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-no-data-mocks'] --- import kbnSharedUxPageNoDataMocksObj from './kbn_shared_ux_page_no_data_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_page_solution_nav.mdx b/api_docs/kbn_shared_ux_page_solution_nav.mdx index 4c5739f8198a4..af86463c2027a 100644 --- a/api_docs/kbn_shared_ux_page_solution_nav.mdx +++ b/api_docs/kbn_shared_ux_page_solution_nav.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-page-solution-nav title: "@kbn/shared-ux-page-solution-nav" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-page-solution-nav plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-page-solution-nav'] --- import kbnSharedUxPageSolutionNavObj from './kbn_shared_ux_page_solution_nav.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx index 64751279933d6..52bb35a6f1125 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views title: "@kbn/shared-ux-prompt-no-data-views" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views'] --- import kbnSharedUxPromptNoDataViewsObj from './kbn_shared_ux_prompt_no_data_views.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx index 3f3d3d1602bc1..d66af5a3e0136 100644 --- a/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx +++ b/api_docs/kbn_shared_ux_prompt_no_data_views_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-no-data-views-mocks title: "@kbn/shared-ux-prompt-no-data-views-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-no-data-views-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-no-data-views-mocks'] --- import kbnSharedUxPromptNoDataViewsMocksObj from './kbn_shared_ux_prompt_no_data_views_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_prompt_not_found.mdx b/api_docs/kbn_shared_ux_prompt_not_found.mdx index 3960fd97a0b0e..0d9a2780ff35c 100644 --- a/api_docs/kbn_shared_ux_prompt_not_found.mdx +++ b/api_docs/kbn_shared_ux_prompt_not_found.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-prompt-not-found title: "@kbn/shared-ux-prompt-not-found" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-prompt-not-found plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-prompt-not-found'] --- import kbnSharedUxPromptNotFoundObj from './kbn_shared_ux_prompt_not_found.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router.mdx b/api_docs/kbn_shared_ux_router.mdx index 02d2b93184945..f7132a40fac54 100644 --- a/api_docs/kbn_shared_ux_router.mdx +++ b/api_docs/kbn_shared_ux_router.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router title: "@kbn/shared-ux-router" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router'] --- import kbnSharedUxRouterObj from './kbn_shared_ux_router.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_router_mocks.mdx b/api_docs/kbn_shared_ux_router_mocks.mdx index cf4fd714809e2..9b6740e9795d3 100644 --- a/api_docs/kbn_shared_ux_router_mocks.mdx +++ b/api_docs/kbn_shared_ux_router_mocks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-router-mocks title: "@kbn/shared-ux-router-mocks" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-router-mocks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-router-mocks'] --- import kbnSharedUxRouterMocksObj from './kbn_shared_ux_router_mocks.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_config.mdx b/api_docs/kbn_shared_ux_storybook_config.mdx index e11e01e54cfb0..f846728b1e6df 100644 --- a/api_docs/kbn_shared_ux_storybook_config.mdx +++ b/api_docs/kbn_shared_ux_storybook_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-config title: "@kbn/shared-ux-storybook-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-config'] --- import kbnSharedUxStorybookConfigObj from './kbn_shared_ux_storybook_config.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_storybook_mock.mdx b/api_docs/kbn_shared_ux_storybook_mock.mdx index fd884b65cbcbe..908ff45486f59 100644 --- a/api_docs/kbn_shared_ux_storybook_mock.mdx +++ b/api_docs/kbn_shared_ux_storybook_mock.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-storybook-mock title: "@kbn/shared-ux-storybook-mock" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-storybook-mock plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-storybook-mock'] --- import kbnSharedUxStorybookMockObj from './kbn_shared_ux_storybook_mock.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_tabbed_modal.mdx b/api_docs/kbn_shared_ux_tabbed_modal.mdx index 982ef4066b3b2..9c3e6b2f662b0 100644 --- a/api_docs/kbn_shared_ux_tabbed_modal.mdx +++ b/api_docs/kbn_shared_ux_tabbed_modal.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-tabbed-modal title: "@kbn/shared-ux-tabbed-modal" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-tabbed-modal plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-tabbed-modal'] --- import kbnSharedUxTabbedModalObj from './kbn_shared_ux_tabbed_modal.devdocs.json'; diff --git a/api_docs/kbn_shared_ux_utility.mdx b/api_docs/kbn_shared_ux_utility.mdx index 6e952f481fa71..0d531e0592db5 100644 --- a/api_docs/kbn_shared_ux_utility.mdx +++ b/api_docs/kbn_shared_ux_utility.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-shared-ux-utility title: "@kbn/shared-ux-utility" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/shared-ux-utility plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/shared-ux-utility'] --- import kbnSharedUxUtilityObj from './kbn_shared_ux_utility.devdocs.json'; diff --git a/api_docs/kbn_slo_schema.mdx b/api_docs/kbn_slo_schema.mdx index fa31b90c36e2b..0c889058d61b3 100644 --- a/api_docs/kbn_slo_schema.mdx +++ b/api_docs/kbn_slo_schema.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-slo-schema title: "@kbn/slo-schema" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/slo-schema plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/slo-schema'] --- import kbnSloSchemaObj from './kbn_slo_schema.devdocs.json'; diff --git a/api_docs/kbn_some_dev_log.mdx b/api_docs/kbn_some_dev_log.mdx index 23a8698ed1c3d..828ea766a3351 100644 --- a/api_docs/kbn_some_dev_log.mdx +++ b/api_docs/kbn_some_dev_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-some-dev-log title: "@kbn/some-dev-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/some-dev-log plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/some-dev-log'] --- import kbnSomeDevLogObj from './kbn_some_dev_log.devdocs.json'; diff --git a/api_docs/kbn_sort_predicates.mdx b/api_docs/kbn_sort_predicates.mdx index 50a5e29ee89b9..65adf8bd65546 100644 --- a/api_docs/kbn_sort_predicates.mdx +++ b/api_docs/kbn_sort_predicates.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-sort-predicates title: "@kbn/sort-predicates" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/sort-predicates plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/sort-predicates'] --- import kbnSortPredicatesObj from './kbn_sort_predicates.devdocs.json'; diff --git a/api_docs/kbn_std.mdx b/api_docs/kbn_std.mdx index 4632a759d1c0f..79e713a9c70a3 100644 --- a/api_docs/kbn_std.mdx +++ b/api_docs/kbn_std.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-std title: "@kbn/std" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/std plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/std'] --- import kbnStdObj from './kbn_std.devdocs.json'; diff --git a/api_docs/kbn_stdio_dev_helpers.mdx b/api_docs/kbn_stdio_dev_helpers.mdx index 7709a066a74d0..ac8f12feca04f 100644 --- a/api_docs/kbn_stdio_dev_helpers.mdx +++ b/api_docs/kbn_stdio_dev_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-stdio-dev-helpers title: "@kbn/stdio-dev-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/stdio-dev-helpers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/stdio-dev-helpers'] --- import kbnStdioDevHelpersObj from './kbn_stdio_dev_helpers.devdocs.json'; diff --git a/api_docs/kbn_storybook.mdx b/api_docs/kbn_storybook.mdx index b6267a4ffecde..b833ae5c0f0b2 100644 --- a/api_docs/kbn_storybook.mdx +++ b/api_docs/kbn_storybook.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-storybook title: "@kbn/storybook" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/storybook plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/storybook'] --- import kbnStorybookObj from './kbn_storybook.devdocs.json'; diff --git a/api_docs/kbn_telemetry_tools.mdx b/api_docs/kbn_telemetry_tools.mdx index d1b39064da422..0067bb89d55df 100644 --- a/api_docs/kbn_telemetry_tools.mdx +++ b/api_docs/kbn_telemetry_tools.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-telemetry-tools title: "@kbn/telemetry-tools" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/telemetry-tools plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/telemetry-tools'] --- import kbnTelemetryToolsObj from './kbn_telemetry_tools.devdocs.json'; diff --git a/api_docs/kbn_test.mdx b/api_docs/kbn_test.mdx index 155433705978c..4e3619ae1b071 100644 --- a/api_docs/kbn_test.mdx +++ b/api_docs/kbn_test.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test title: "@kbn/test" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test'] --- import kbnTestObj from './kbn_test.devdocs.json'; diff --git a/api_docs/kbn_test_eui_helpers.mdx b/api_docs/kbn_test_eui_helpers.mdx index 5fa7d9c8d3092..e8b08b03ded62 100644 --- a/api_docs/kbn_test_eui_helpers.mdx +++ b/api_docs/kbn_test_eui_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-eui-helpers title: "@kbn/test-eui-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-eui-helpers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-eui-helpers'] --- import kbnTestEuiHelpersObj from './kbn_test_eui_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_jest_helpers.mdx b/api_docs/kbn_test_jest_helpers.mdx index a5fbd30feb207..f257ff67eb8cd 100644 --- a/api_docs/kbn_test_jest_helpers.mdx +++ b/api_docs/kbn_test_jest_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-jest-helpers title: "@kbn/test-jest-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-jest-helpers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-jest-helpers'] --- import kbnTestJestHelpersObj from './kbn_test_jest_helpers.devdocs.json'; diff --git a/api_docs/kbn_test_subj_selector.mdx b/api_docs/kbn_test_subj_selector.mdx index 5884b187e5cbb..4fdf7ceddf692 100644 --- a/api_docs/kbn_test_subj_selector.mdx +++ b/api_docs/kbn_test_subj_selector.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-test-subj-selector title: "@kbn/test-subj-selector" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/test-subj-selector plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/test-subj-selector'] --- import kbnTestSubjSelectorObj from './kbn_test_subj_selector.devdocs.json'; diff --git a/api_docs/kbn_text_based_editor.mdx b/api_docs/kbn_text_based_editor.mdx index 9edaf4d2af2c8..d32510ebfee71 100644 --- a/api_docs/kbn_text_based_editor.mdx +++ b/api_docs/kbn_text_based_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-text-based-editor title: "@kbn/text-based-editor" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/text-based-editor plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/text-based-editor'] --- import kbnTextBasedEditorObj from './kbn_text_based_editor.devdocs.json'; diff --git a/api_docs/kbn_timerange.mdx b/api_docs/kbn_timerange.mdx index 505143d3cd8a4..1c7d239dfdb24 100644 --- a/api_docs/kbn_timerange.mdx +++ b/api_docs/kbn_timerange.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-timerange title: "@kbn/timerange" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/timerange plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/timerange'] --- import kbnTimerangeObj from './kbn_timerange.devdocs.json'; diff --git a/api_docs/kbn_tooling_log.mdx b/api_docs/kbn_tooling_log.mdx index 6bf29d329cf17..ce8055b764097 100644 --- a/api_docs/kbn_tooling_log.mdx +++ b/api_docs/kbn_tooling_log.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-tooling-log title: "@kbn/tooling-log" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/tooling-log plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/tooling-log'] --- import kbnToolingLogObj from './kbn_tooling_log.devdocs.json'; diff --git a/api_docs/kbn_triggers_actions_ui_types.mdx b/api_docs/kbn_triggers_actions_ui_types.mdx index 3ea4774d0bd2a..3c2462c004bd9 100644 --- a/api_docs/kbn_triggers_actions_ui_types.mdx +++ b/api_docs/kbn_triggers_actions_ui_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-triggers-actions-ui-types title: "@kbn/triggers-actions-ui-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/triggers-actions-ui-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/triggers-actions-ui-types'] --- import kbnTriggersActionsUiTypesObj from './kbn_triggers_actions_ui_types.devdocs.json'; diff --git a/api_docs/kbn_try_in_console.mdx b/api_docs/kbn_try_in_console.mdx index 424c3b238a7e1..8398ddf20be1d 100644 --- a/api_docs/kbn_try_in_console.mdx +++ b/api_docs/kbn_try_in_console.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-try-in-console title: "@kbn/try-in-console" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/try-in-console plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/try-in-console'] --- import kbnTryInConsoleObj from './kbn_try_in_console.devdocs.json'; diff --git a/api_docs/kbn_ts_projects.mdx b/api_docs/kbn_ts_projects.mdx index a1a56acaa08dd..008137caa6e13 100644 --- a/api_docs/kbn_ts_projects.mdx +++ b/api_docs/kbn_ts_projects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ts-projects title: "@kbn/ts-projects" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ts-projects plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ts-projects'] --- import kbnTsProjectsObj from './kbn_ts_projects.devdocs.json'; diff --git a/api_docs/kbn_typed_react_router_config.mdx b/api_docs/kbn_typed_react_router_config.mdx index 133207d73e809..071842c337802 100644 --- a/api_docs/kbn_typed_react_router_config.mdx +++ b/api_docs/kbn_typed_react_router_config.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-typed-react-router-config title: "@kbn/typed-react-router-config" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/typed-react-router-config plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/typed-react-router-config'] --- import kbnTypedReactRouterConfigObj from './kbn_typed_react_router_config.devdocs.json'; diff --git a/api_docs/kbn_ui_actions_browser.mdx b/api_docs/kbn_ui_actions_browser.mdx index db0038e278edf..d190fcfd263b9 100644 --- a/api_docs/kbn_ui_actions_browser.mdx +++ b/api_docs/kbn_ui_actions_browser.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-actions-browser title: "@kbn/ui-actions-browser" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-actions-browser plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-actions-browser'] --- import kbnUiActionsBrowserObj from './kbn_ui_actions_browser.devdocs.json'; diff --git a/api_docs/kbn_ui_shared_deps_src.mdx b/api_docs/kbn_ui_shared_deps_src.mdx index e609e7bd8532e..d794b08507a1c 100644 --- a/api_docs/kbn_ui_shared_deps_src.mdx +++ b/api_docs/kbn_ui_shared_deps_src.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-shared-deps-src title: "@kbn/ui-shared-deps-src" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-shared-deps-src plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-shared-deps-src'] --- import kbnUiSharedDepsSrcObj from './kbn_ui_shared_deps_src.devdocs.json'; diff --git a/api_docs/kbn_ui_theme.mdx b/api_docs/kbn_ui_theme.mdx index 08a5368cb36f4..8ed6b1f0b1f9c 100644 --- a/api_docs/kbn_ui_theme.mdx +++ b/api_docs/kbn_ui_theme.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-ui-theme title: "@kbn/ui-theme" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/ui-theme plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/ui-theme'] --- import kbnUiThemeObj from './kbn_ui_theme.devdocs.json'; diff --git a/api_docs/kbn_unified_data_table.mdx b/api_docs/kbn_unified_data_table.mdx index 14645013d4e93..949d2b5054c32 100644 --- a/api_docs/kbn_unified_data_table.mdx +++ b/api_docs/kbn_unified_data_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-data-table title: "@kbn/unified-data-table" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-data-table plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-data-table'] --- import kbnUnifiedDataTableObj from './kbn_unified_data_table.devdocs.json'; diff --git a/api_docs/kbn_unified_doc_viewer.mdx b/api_docs/kbn_unified_doc_viewer.mdx index c66e5afd4e514..83591ac81f067 100644 --- a/api_docs/kbn_unified_doc_viewer.mdx +++ b/api_docs/kbn_unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-doc-viewer title: "@kbn/unified-doc-viewer" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-doc-viewer plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-doc-viewer'] --- import kbnUnifiedDocViewerObj from './kbn_unified_doc_viewer.devdocs.json'; diff --git a/api_docs/kbn_unified_field_list.mdx b/api_docs/kbn_unified_field_list.mdx index d7fa697e42195..4ab725a0f085a 100644 --- a/api_docs/kbn_unified_field_list.mdx +++ b/api_docs/kbn_unified_field_list.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unified-field-list title: "@kbn/unified-field-list" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unified-field-list plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unified-field-list'] --- import kbnUnifiedFieldListObj from './kbn_unified_field_list.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_badge.mdx b/api_docs/kbn_unsaved_changes_badge.mdx index bc261faf6bcca..046859418c3d7 100644 --- a/api_docs/kbn_unsaved_changes_badge.mdx +++ b/api_docs/kbn_unsaved_changes_badge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-badge title: "@kbn/unsaved-changes-badge" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-badge plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-badge'] --- import kbnUnsavedChangesBadgeObj from './kbn_unsaved_changes_badge.devdocs.json'; diff --git a/api_docs/kbn_unsaved_changes_prompt.mdx b/api_docs/kbn_unsaved_changes_prompt.mdx index edebe944f9ab6..ad3e54d80b024 100644 --- a/api_docs/kbn_unsaved_changes_prompt.mdx +++ b/api_docs/kbn_unsaved_changes_prompt.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-unsaved-changes-prompt title: "@kbn/unsaved-changes-prompt" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/unsaved-changes-prompt plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/unsaved-changes-prompt'] --- import kbnUnsavedChangesPromptObj from './kbn_unsaved_changes_prompt.devdocs.json'; diff --git a/api_docs/kbn_use_tracked_promise.mdx b/api_docs/kbn_use_tracked_promise.mdx index 3746502d352ff..cc1285171c6be 100644 --- a/api_docs/kbn_use_tracked_promise.mdx +++ b/api_docs/kbn_use_tracked_promise.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-use-tracked-promise title: "@kbn/use-tracked-promise" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/use-tracked-promise plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/use-tracked-promise'] --- import kbnUseTrackedPromiseObj from './kbn_use_tracked_promise.devdocs.json'; diff --git a/api_docs/kbn_user_profile_components.mdx b/api_docs/kbn_user_profile_components.mdx index 2333053251584..c3de2bd210c4c 100644 --- a/api_docs/kbn_user_profile_components.mdx +++ b/api_docs/kbn_user_profile_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-user-profile-components title: "@kbn/user-profile-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/user-profile-components plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/user-profile-components'] --- import kbnUserProfileComponentsObj from './kbn_user_profile_components.devdocs.json'; diff --git a/api_docs/kbn_utility_types.mdx b/api_docs/kbn_utility_types.mdx index dbf4bc7787baa..902da4bd5b1d7 100644 --- a/api_docs/kbn_utility_types.mdx +++ b/api_docs/kbn_utility_types.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types title: "@kbn/utility-types" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types'] --- import kbnUtilityTypesObj from './kbn_utility_types.devdocs.json'; diff --git a/api_docs/kbn_utility_types_jest.mdx b/api_docs/kbn_utility_types_jest.mdx index cc6d3bac0b63c..0af811283ea18 100644 --- a/api_docs/kbn_utility_types_jest.mdx +++ b/api_docs/kbn_utility_types_jest.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utility-types-jest title: "@kbn/utility-types-jest" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utility-types-jest plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utility-types-jest'] --- import kbnUtilityTypesJestObj from './kbn_utility_types_jest.devdocs.json'; diff --git a/api_docs/kbn_utils.mdx b/api_docs/kbn_utils.mdx index 0d5c0c8ac7bf6..3aad081e416e5 100644 --- a/api_docs/kbn_utils.mdx +++ b/api_docs/kbn_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-utils title: "@kbn/utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/utils'] --- import kbnUtilsObj from './kbn_utils.devdocs.json'; diff --git a/api_docs/kbn_visualization_ui_components.mdx b/api_docs/kbn_visualization_ui_components.mdx index 81aa7c19249b9..703f807fd88da 100644 --- a/api_docs/kbn_visualization_ui_components.mdx +++ b/api_docs/kbn_visualization_ui_components.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-ui-components title: "@kbn/visualization-ui-components" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-ui-components plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-ui-components'] --- import kbnVisualizationUiComponentsObj from './kbn_visualization_ui_components.devdocs.json'; diff --git a/api_docs/kbn_visualization_utils.mdx b/api_docs/kbn_visualization_utils.mdx index ded1ecf90319c..d4a07162ebc11 100644 --- a/api_docs/kbn_visualization_utils.mdx +++ b/api_docs/kbn_visualization_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-visualization-utils title: "@kbn/visualization-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/visualization-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/visualization-utils'] --- import kbnVisualizationUtilsObj from './kbn_visualization_utils.devdocs.json'; diff --git a/api_docs/kbn_xstate_utils.mdx b/api_docs/kbn_xstate_utils.mdx index 2ce1cc1af731e..c26d937f8e849 100644 --- a/api_docs/kbn_xstate_utils.mdx +++ b/api_docs/kbn_xstate_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-xstate-utils title: "@kbn/xstate-utils" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/xstate-utils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/xstate-utils'] --- import kbnXstateUtilsObj from './kbn_xstate_utils.devdocs.json'; diff --git a/api_docs/kbn_yarn_lock_validator.mdx b/api_docs/kbn_yarn_lock_validator.mdx index 747970143a51a..926a0cff992a2 100644 --- a/api_docs/kbn_yarn_lock_validator.mdx +++ b/api_docs/kbn_yarn_lock_validator.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-yarn-lock-validator title: "@kbn/yarn-lock-validator" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/yarn-lock-validator plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/yarn-lock-validator'] --- import kbnYarnLockValidatorObj from './kbn_yarn_lock_validator.devdocs.json'; diff --git a/api_docs/kbn_zod_helpers.mdx b/api_docs/kbn_zod_helpers.mdx index ff375219d35e8..03c12ce98a52c 100644 --- a/api_docs/kbn_zod_helpers.mdx +++ b/api_docs/kbn_zod_helpers.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kbn-zod-helpers title: "@kbn/zod-helpers" image: https://source.unsplash.com/400x175/?github description: API docs for the @kbn/zod-helpers plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', '@kbn/zod-helpers'] --- import kbnZodHelpersObj from './kbn_zod_helpers.devdocs.json'; diff --git a/api_docs/kibana_overview.mdx b/api_docs/kibana_overview.mdx index 89b61748928ff..0b188a61c7f84 100644 --- a/api_docs/kibana_overview.mdx +++ b/api_docs/kibana_overview.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaOverview title: "kibanaOverview" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaOverview plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaOverview'] --- import kibanaOverviewObj from './kibana_overview.devdocs.json'; diff --git a/api_docs/kibana_react.mdx b/api_docs/kibana_react.mdx index 49ede3b7aa002..0601f358649ca 100644 --- a/api_docs/kibana_react.mdx +++ b/api_docs/kibana_react.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaReact title: "kibanaReact" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaReact plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaReact'] --- import kibanaReactObj from './kibana_react.devdocs.json'; diff --git a/api_docs/kibana_utils.mdx b/api_docs/kibana_utils.mdx index 4f2fb608278fd..595ae94c2cfa9 100644 --- a/api_docs/kibana_utils.mdx +++ b/api_docs/kibana_utils.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kibanaUtils title: "kibanaUtils" image: https://source.unsplash.com/400x175/?github description: API docs for the kibanaUtils plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kibanaUtils'] --- import kibanaUtilsObj from './kibana_utils.devdocs.json'; diff --git a/api_docs/kubernetes_security.mdx b/api_docs/kubernetes_security.mdx index ba8f3623888c8..67946b4f21bc3 100644 --- a/api_docs/kubernetes_security.mdx +++ b/api_docs/kubernetes_security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/kubernetesSecurity title: "kubernetesSecurity" image: https://source.unsplash.com/400x175/?github description: API docs for the kubernetesSecurity plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'kubernetesSecurity'] --- import kubernetesSecurityObj from './kubernetes_security.devdocs.json'; diff --git a/api_docs/lens.mdx b/api_docs/lens.mdx index aec896d5325bc..d6bbda3c04161 100644 --- a/api_docs/lens.mdx +++ b/api_docs/lens.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lens title: "lens" image: https://source.unsplash.com/400x175/?github description: API docs for the lens plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lens'] --- import lensObj from './lens.devdocs.json'; diff --git a/api_docs/license_api_guard.mdx b/api_docs/license_api_guard.mdx index 363fed87120b9..6a48fd421d7c5 100644 --- a/api_docs/license_api_guard.mdx +++ b/api_docs/license_api_guard.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseApiGuard title: "licenseApiGuard" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseApiGuard plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseApiGuard'] --- import licenseApiGuardObj from './license_api_guard.devdocs.json'; diff --git a/api_docs/license_management.mdx b/api_docs/license_management.mdx index 238ad1bf95988..718e09f730703 100644 --- a/api_docs/license_management.mdx +++ b/api_docs/license_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licenseManagement title: "licenseManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the licenseManagement plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licenseManagement'] --- import licenseManagementObj from './license_management.devdocs.json'; diff --git a/api_docs/licensing.mdx b/api_docs/licensing.mdx index c757ae7e44b5b..675530d73f1b1 100644 --- a/api_docs/licensing.mdx +++ b/api_docs/licensing.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/licensing title: "licensing" image: https://source.unsplash.com/400x175/?github description: API docs for the licensing plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'licensing'] --- import licensingObj from './licensing.devdocs.json'; diff --git a/api_docs/links.mdx b/api_docs/links.mdx index 457976299070a..ca8c9a86beb91 100644 --- a/api_docs/links.mdx +++ b/api_docs/links.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/links title: "links" image: https://source.unsplash.com/400x175/?github description: API docs for the links plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'links'] --- import linksObj from './links.devdocs.json'; diff --git a/api_docs/lists.mdx b/api_docs/lists.mdx index 80ee9c6497177..3c890f58aae59 100644 --- a/api_docs/lists.mdx +++ b/api_docs/lists.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/lists title: "lists" image: https://source.unsplash.com/400x175/?github description: API docs for the lists plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'lists'] --- import listsObj from './lists.devdocs.json'; diff --git a/api_docs/logs_data_access.mdx b/api_docs/logs_data_access.mdx index 89ce057846c73..3ada2c6b3e309 100644 --- a/api_docs/logs_data_access.mdx +++ b/api_docs/logs_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsDataAccess title: "logsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the logsDataAccess plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsDataAccess'] --- import logsDataAccessObj from './logs_data_access.devdocs.json'; diff --git a/api_docs/logs_explorer.mdx b/api_docs/logs_explorer.mdx index 45b4c1392be72..c5fb38b618c6a 100644 --- a/api_docs/logs_explorer.mdx +++ b/api_docs/logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsExplorer title: "logsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the logsExplorer plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsExplorer'] --- import logsExplorerObj from './logs_explorer.devdocs.json'; diff --git a/api_docs/logs_shared.mdx b/api_docs/logs_shared.mdx index 45f45dad5ab44..547e16d96533e 100644 --- a/api_docs/logs_shared.mdx +++ b/api_docs/logs_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/logsShared title: "logsShared" image: https://source.unsplash.com/400x175/?github description: API docs for the logsShared plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'logsShared'] --- import logsSharedObj from './logs_shared.devdocs.json'; diff --git a/api_docs/management.mdx b/api_docs/management.mdx index d3dd2dbedba75..00ecfce7e4ec7 100644 --- a/api_docs/management.mdx +++ b/api_docs/management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/management title: "management" image: https://source.unsplash.com/400x175/?github description: API docs for the management plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'management'] --- import managementObj from './management.devdocs.json'; diff --git a/api_docs/maps.mdx b/api_docs/maps.mdx index a57a144a194a2..2992d52fb1548 100644 --- a/api_docs/maps.mdx +++ b/api_docs/maps.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/maps title: "maps" image: https://source.unsplash.com/400x175/?github description: API docs for the maps plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'maps'] --- import mapsObj from './maps.devdocs.json'; diff --git a/api_docs/maps_ems.mdx b/api_docs/maps_ems.mdx index cc1ca399f96e4..edf6720a36908 100644 --- a/api_docs/maps_ems.mdx +++ b/api_docs/maps_ems.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mapsEms title: "mapsEms" image: https://source.unsplash.com/400x175/?github description: API docs for the mapsEms plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mapsEms'] --- import mapsEmsObj from './maps_ems.devdocs.json'; diff --git a/api_docs/metrics_data_access.mdx b/api_docs/metrics_data_access.mdx index 1fc5ef2dc891f..11e9dc68f7edb 100644 --- a/api_docs/metrics_data_access.mdx +++ b/api_docs/metrics_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/metricsDataAccess title: "metricsDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the metricsDataAccess plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'metricsDataAccess'] --- import metricsDataAccessObj from './metrics_data_access.devdocs.json'; diff --git a/api_docs/ml.mdx b/api_docs/ml.mdx index 2bb16023ac1b9..9ff15f0e1198f 100644 --- a/api_docs/ml.mdx +++ b/api_docs/ml.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ml title: "ml" image: https://source.unsplash.com/400x175/?github description: API docs for the ml plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ml'] --- import mlObj from './ml.devdocs.json'; diff --git a/api_docs/mock_idp_plugin.mdx b/api_docs/mock_idp_plugin.mdx index e34875769829f..5f0adc9bf8052 100644 --- a/api_docs/mock_idp_plugin.mdx +++ b/api_docs/mock_idp_plugin.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/mockIdpPlugin title: "mockIdpPlugin" image: https://source.unsplash.com/400x175/?github description: API docs for the mockIdpPlugin plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'mockIdpPlugin'] --- import mockIdpPluginObj from './mock_idp_plugin.devdocs.json'; diff --git a/api_docs/monitoring.mdx b/api_docs/monitoring.mdx index a5a8b8016124f..214721933971b 100644 --- a/api_docs/monitoring.mdx +++ b/api_docs/monitoring.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoring title: "monitoring" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoring plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoring'] --- import monitoringObj from './monitoring.devdocs.json'; diff --git a/api_docs/monitoring_collection.mdx b/api_docs/monitoring_collection.mdx index 7a0bb24f28f2f..3ee2bf7e651a8 100644 --- a/api_docs/monitoring_collection.mdx +++ b/api_docs/monitoring_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/monitoringCollection title: "monitoringCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the monitoringCollection plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'monitoringCollection'] --- import monitoringCollectionObj from './monitoring_collection.devdocs.json'; diff --git a/api_docs/navigation.mdx b/api_docs/navigation.mdx index 5a3e285e64c7f..7a49d7bb4b78c 100644 --- a/api_docs/navigation.mdx +++ b/api_docs/navigation.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/navigation title: "navigation" image: https://source.unsplash.com/400x175/?github description: API docs for the navigation plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'navigation'] --- import navigationObj from './navigation.devdocs.json'; diff --git a/api_docs/newsfeed.mdx b/api_docs/newsfeed.mdx index 48664d249cf29..f2144a08ad60c 100644 --- a/api_docs/newsfeed.mdx +++ b/api_docs/newsfeed.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/newsfeed title: "newsfeed" image: https://source.unsplash.com/400x175/?github description: API docs for the newsfeed plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'newsfeed'] --- import newsfeedObj from './newsfeed.devdocs.json'; diff --git a/api_docs/no_data_page.mdx b/api_docs/no_data_page.mdx index ff65f63d2451a..ff3c3703ac445 100644 --- a/api_docs/no_data_page.mdx +++ b/api_docs/no_data_page.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/noDataPage title: "noDataPage" image: https://source.unsplash.com/400x175/?github description: API docs for the noDataPage plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'noDataPage'] --- import noDataPageObj from './no_data_page.devdocs.json'; diff --git a/api_docs/notifications.mdx b/api_docs/notifications.mdx index aa2f8dd7d74b9..4bde97507c10b 100644 --- a/api_docs/notifications.mdx +++ b/api_docs/notifications.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/notifications title: "notifications" image: https://source.unsplash.com/400x175/?github description: API docs for the notifications plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'notifications'] --- import notificationsObj from './notifications.devdocs.json'; diff --git a/api_docs/observability.devdocs.json b/api_docs/observability.devdocs.json index 47e68f63b1d39..7082446850312 100644 --- a/api_docs/observability.devdocs.json +++ b/api_docs/observability.devdocs.json @@ -1,177 +1,70 @@ { "id": "observability", "client": { - "classes": [ + "classes": [], + "functions": [ { "parentPluginId": "observability", - "id": "def-public.AutocompleteField", - "type": "Class", + "id": "def-public.AlertSummary", + "type": "Function", "tags": [], - "label": "AutocompleteField", + "label": "AlertSummary", "description": [], "signature": [ - { - "pluginId": "observability", - "scope": "public", - "docId": "kibObservabilityPluginApi", - "section": "def-public.AutocompleteField", - "text": "AutocompleteField" - }, - " extends React.Component<AutocompleteFieldProps, AutocompleteFieldState, any>" + "(props: ", + "AlertSummaryProps", + ") => JSX.Element" ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/index.tsx", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "observability", - "id": "def-public.AutocompleteField.state", + "id": "def-public.AlertSummary.$1", "type": "Object", "tags": [], - "label": "state", - "description": [], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "observability", - "id": "def-public.AutocompleteField.state.areSuggestionsVisible", - "type": "boolean", - "tags": [], - "label": "areSuggestionsVisible", - "description": [], - "signature": [ - "false" - ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-public.AutocompleteField.state.isFocused", - "type": "boolean", - "tags": [], - "label": "isFocused", - "description": [], - "signature": [ - "false" - ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", - "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-public.AutocompleteField.state.selectedIndex", - "type": "Uncategorized", - "tags": [], - "label": "selectedIndex", - "description": [], - "signature": [ - "null" - ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", - "deprecated": false, - "trackAdoption": false - } - ] - }, - { - "parentPluginId": "observability", - "id": "def-public.AutocompleteField.render", - "type": "Function", - "tags": [], - "label": "render", - "description": [], - "signature": [ - "() => JSX.Element" - ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "observability", - "id": "def-public.AutocompleteField.componentDidMount", - "type": "Function", - "tags": [], - "label": "componentDidMount", - "description": [], - "signature": [ - "() => void" - ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [] - }, - { - "parentPluginId": "observability", - "id": "def-public.AutocompleteField.componentDidUpdate", - "type": "Function", - "tags": [], - "label": "componentDidUpdate", + "label": "props", "description": [], "signature": [ - "(prevProps: AutocompleteFieldProps) => void" + "AlertSummaryProps" ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/index.tsx", "deprecated": false, "trackAdoption": false, - "children": [ - { - "parentPluginId": "observability", - "id": "def-public.AutocompleteField.componentDidUpdate.$1", - "type": "Object", - "tags": [], - "label": "prevProps", - "description": [], - "signature": [ - "AutocompleteFieldProps" - ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/autocomplete_field/autocomplete_field.tsx", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [] + "isRequired": true } ], + "returnComment": [], "initialIsOpen": false - } - ], - "functions": [ + }, { "parentPluginId": "observability", - "id": "def-public.AlertSummary", + "id": "def-public.AutocompleteField", "type": "Function", "tags": [], - "label": "AlertSummary", + "label": "AutocompleteField", "description": [], "signature": [ - "({ alert, alertSummaryFields }: AlertSummaryProps) => JSX.Element" + "(props: ", + "AutocompleteFieldProps", + ") => JSX.Element" ], - "path": "x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx", "deprecated": false, "trackAdoption": false, "children": [ { "parentPluginId": "observability", - "id": "def-public.AlertSummary.$1", + "id": "def-public.AutocompleteField.$1", "type": "Object", "tags": [], - "label": "{ alert, alertSummaryFields }", + "label": "props", "description": [], "signature": [ - "AlertSummaryProps" + "AutocompleteFieldProps" ], - "path": "x-pack/plugins/observability_solution/observability/public/pages/alert_details/components/alert_summary.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -457,9 +350,11 @@ "label": "DatePicker", "description": [], "signature": [ - "({\n rangeFrom,\n rangeTo,\n refreshPaused,\n refreshInterval,\n width = 'restricted',\n onTimeRangeRefresh,\n}: DatePickerProps) => JSX.Element" + "(props: ", + "DatePickerProps", + ") => JSX.Element" ], - "path": "x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/date_picker.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/index.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -468,12 +363,12 @@ "id": "def-public.DatePicker.$1", "type": "Object", "tags": [], - "label": "{\n rangeFrom,\n rangeTo,\n refreshPaused,\n refreshInterval,\n width = 'restricted',\n onTimeRangeRefresh,\n}", + "label": "props", "description": [], "signature": [ "DatePickerProps" ], - "path": "x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/date_picker.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/pages/overview/components/date_picker/index.tsx", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -791,49 +686,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "observability", - "id": "def-public.getElasticsearchQueryOrThrow", - "type": "Function", - "tags": [], - "label": "getElasticsearchQueryOrThrow", - "description": [], - "signature": [ - "(kuery: string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }) => never[] | ", - "QueryDslQueryContainer", - " | { bool: ", - { - "pluginId": "@kbn/es-query", - "scope": "common", - "docId": "kibKbnEsQueryPluginApi", - "section": "def-common.BoolQuery", - "text": "BoolQuery" - }, - "; }" - ], - "path": "x-pack/plugins/observability_solution/observability/common/utils/parse_kuery.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "observability", - "id": "def-public.getElasticsearchQueryOrThrow.$1", - "type": "CompoundType", - "tags": [], - "label": "kuery", - "description": [], - "signature": [ - "string | { kqlQuery: string; filters: { meta: { alias?: string | null | undefined; disabled?: boolean | undefined; negate?: boolean | undefined; controlledBy?: string | undefined; group?: string | undefined; index?: string | undefined; isMultiIndex?: boolean | undefined; type?: string | undefined; key?: string | undefined; field?: string | undefined; params?: any; value?: string | undefined; }; query: { [x: string]: any; }; }[]; }" - ], - "path": "x-pack/plugins/observability_solution/observability/common/utils/parse_kuery.ts", - "deprecated": false, - "trackAdoption": false, - "isRequired": true - } - ], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "observability", "id": "def-public.getGroupFilters", @@ -1079,9 +931,11 @@ "label": "RuleConditionChart", "description": [], "signature": [ - "({\n metricExpression,\n searchConfiguration,\n dataView,\n groupBy,\n error,\n annotations,\n timeRange,\n chartOptions: { seriesType, interval } = {},\n additionalFilters = [],\n}: RuleConditionChartProps) => JSX.Element" + "(props: ", + "RuleConditionChartProps", + ") => JSX.Element" ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/rule_condition_chart.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/index.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -1090,12 +944,12 @@ "id": "def-public.RuleConditionChart.$1", "type": "Object", "tags": [], - "label": "{\n metricExpression,\n searchConfiguration,\n dataView,\n groupBy,\n error,\n annotations,\n timeRange,\n chartOptions: { seriesType, interval } = {},\n additionalFilters = [],\n}", + "label": "props", "description": [], "signature": [ "RuleConditionChartProps" ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/rule_condition_chart.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/components/rule_condition_chart/index.tsx", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -1112,9 +966,11 @@ "label": "RuleFlyoutKueryBar", "description": [], "signature": [ - "({\n derivedIndexPattern,\n onSubmit,\n onChange,\n value,\n placeholder,\n curryLoadSuggestions = defaultCurryLoadSuggestions,\n compressed,\n}: Props) => JSX.Element" + "(props: ", + "RuleFlyoutKueryBarProps", + ") => JSX.Element" ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx", "deprecated": false, "trackAdoption": false, "children": [ @@ -1123,12 +979,12 @@ "id": "def-public.RuleFlyoutKueryBar.$1", "type": "Object", "tags": [], - "label": "{\n derivedIndexPattern,\n onSubmit,\n onChange,\n value,\n placeholder,\n curryLoadSuggestions = defaultCurryLoadSuggestions,\n compressed,\n}", + "label": "props", "description": [], "signature": [ - "Props" + "RuleFlyoutKueryBarProps" ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/kuery_bar.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx", "deprecated": false, "trackAdoption": false, "isRequired": true @@ -1172,29 +1028,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "observability", - "id": "def-public.useCreateRule", - "type": "Function", - "tags": [], - "label": "useCreateRule", - "description": [], - "signature": [ - "() => ", - "UseMutationResult", - "<", - "CreateRuleResponse", - "<Params>, Error, { rule: ", - "CreateRuleRequestBody", - "<Params>; }, unknown>" - ], - "path": "x-pack/plugins/observability_solution/observability/public/hooks/use_create_rule.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "observability", "id": "def-public.useFetchDataViews", @@ -1234,23 +1067,6 @@ "returnComment": [], "initialIsOpen": false }, - { - "parentPluginId": "observability", - "id": "def-public.useGetFilteredRuleTypes", - "type": "Function", - "tags": [], - "label": "useGetFilteredRuleTypes", - "description": [], - "signature": [ - "() => string[]" - ], - "path": "x-pack/plugins/observability_solution/observability/public/hooks/use_get_filtered_rule_types.ts", - "deprecated": false, - "trackAdoption": false, - "children": [], - "returnComment": [], - "initialIsOpen": false - }, { "parentPluginId": "observability", "id": "def-public.useSummaryTimeRange", @@ -1337,42 +1153,31 @@ "label": "WithKueryAutocompletion", "description": [], "signature": [ - "React.FunctionComponent<Omit<WithKueryAutocompletionLifecycleProps, \"kibana\">>" + "(props: ", + "WithKueryAutocompletionLifecycleProps", + ") => JSX.Element" ], - "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/with_kuery_autocompletion.tsx", + "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx", "deprecated": false, "trackAdoption": false, - "returnComment": [], "children": [ { "parentPluginId": "observability", "id": "def-public.WithKueryAutocompletion.$1", - "type": "CompoundType", + "type": "Object", "tags": [], "label": "props", "description": [], "signature": [ - "P & { children?: React.ReactNode; }" + "WithKueryAutocompletionLifecycleProps" ], - "path": "node_modules/@types/react/index.d.ts", + "path": "x-pack/plugins/observability_solution/observability/public/components/rule_kql_filter/index.tsx", "deprecated": false, - "trackAdoption": false - }, - { - "parentPluginId": "observability", - "id": "def-public.WithKueryAutocompletion.$2", - "type": "Any", - "tags": [], - "label": "context", - "description": [], - "signature": [ - "any" - ], - "path": "node_modules/@types/react/index.d.ts", - "deprecated": false, - "trackAdoption": false + "trackAdoption": false, + "isRequired": true } ], + "returnComment": [], "initialIsOpen": false } ], diff --git a/api_docs/observability.mdx b/api_docs/observability.mdx index 7e8630ed6495e..33cabc8ad3f72 100644 --- a/api_docs/observability.mdx +++ b/api_docs/observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observability title: "observability" image: https://source.unsplash.com/400x175/?github description: API docs for the observability plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observability'] --- import observabilityObj from './observability.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 705 | 2 | 696 | 16 | +| 693 | 2 | 686 | 22 | ## Client @@ -34,9 +34,6 @@ Contact [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/ ### Functions <DocDefinitionList data={observabilityObj.client.functions}/> -### Classes -<DocDefinitionList data={observabilityObj.client.classes}/> - ### Interfaces <DocDefinitionList data={observabilityObj.client.interfaces}/> diff --git a/api_docs/observability_a_i_assistant.mdx b/api_docs/observability_a_i_assistant.mdx index f599121b20b5c..8999c4197a467 100644 --- a/api_docs/observability_a_i_assistant.mdx +++ b/api_docs/observability_a_i_assistant.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistant title: "observabilityAIAssistant" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistant plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistant'] --- import observabilityAIAssistantObj from './observability_a_i_assistant.devdocs.json'; diff --git a/api_docs/observability_a_i_assistant_app.mdx b/api_docs/observability_a_i_assistant_app.mdx index d39aa36e76bb4..016e6e95fb218 100644 --- a/api_docs/observability_a_i_assistant_app.mdx +++ b/api_docs/observability_a_i_assistant_app.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAIAssistantApp title: "observabilityAIAssistantApp" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAIAssistantApp plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAIAssistantApp'] --- import observabilityAIAssistantAppObj from './observability_a_i_assistant_app.devdocs.json'; diff --git a/api_docs/observability_ai_assistant_management.mdx b/api_docs/observability_ai_assistant_management.mdx index 09e6010905020..0f660661a9d38 100644 --- a/api_docs/observability_ai_assistant_management.mdx +++ b/api_docs/observability_ai_assistant_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityAiAssistantManagement title: "observabilityAiAssistantManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityAiAssistantManagement plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityAiAssistantManagement'] --- import observabilityAiAssistantManagementObj from './observability_ai_assistant_management.devdocs.json'; diff --git a/api_docs/observability_logs_explorer.mdx b/api_docs/observability_logs_explorer.mdx index ae5a030638640..e20abf2365cbb 100644 --- a/api_docs/observability_logs_explorer.mdx +++ b/api_docs/observability_logs_explorer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityLogsExplorer title: "observabilityLogsExplorer" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityLogsExplorer plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityLogsExplorer'] --- import observabilityLogsExplorerObj from './observability_logs_explorer.devdocs.json'; diff --git a/api_docs/observability_onboarding.mdx b/api_docs/observability_onboarding.mdx index bc199f3aead93..df6de3ddf4ea0 100644 --- a/api_docs/observability_onboarding.mdx +++ b/api_docs/observability_onboarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityOnboarding title: "observabilityOnboarding" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityOnboarding plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityOnboarding'] --- import observabilityOnboardingObj from './observability_onboarding.devdocs.json'; diff --git a/api_docs/observability_shared.mdx b/api_docs/observability_shared.mdx index 44540c21bc620..8cee439886545 100644 --- a/api_docs/observability_shared.mdx +++ b/api_docs/observability_shared.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/observabilityShared title: "observabilityShared" image: https://source.unsplash.com/400x175/?github description: API docs for the observabilityShared plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'observabilityShared'] --- import observabilitySharedObj from './observability_shared.devdocs.json'; diff --git a/api_docs/osquery.mdx b/api_docs/osquery.mdx index 66af140dfe2cb..99d5d1661fc2a 100644 --- a/api_docs/osquery.mdx +++ b/api_docs/osquery.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/osquery title: "osquery" image: https://source.unsplash.com/400x175/?github description: API docs for the osquery plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'osquery'] --- import osqueryObj from './osquery.devdocs.json'; diff --git a/api_docs/painless_lab.mdx b/api_docs/painless_lab.mdx index 60a74ea60e866..a0e5fc246d1d0 100644 --- a/api_docs/painless_lab.mdx +++ b/api_docs/painless_lab.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/painlessLab title: "painlessLab" image: https://source.unsplash.com/400x175/?github description: API docs for the painlessLab plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'painlessLab'] --- import painlessLabObj from './painless_lab.devdocs.json'; diff --git a/api_docs/plugin_directory.mdx b/api_docs/plugin_directory.mdx index 6c5f77780edf4..5305a82346a4c 100644 --- a/api_docs/plugin_directory.mdx +++ b/api_docs/plugin_directory.mdx @@ -7,7 +7,7 @@ id: kibDevDocsPluginDirectory slug: /kibana-dev-docs/api-meta/plugin-api-directory title: Directory description: Directory of public APIs available through plugins or packages. -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana'] --- @@ -15,13 +15,13 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | Count | Plugins or Packages with a <br /> public API | Number of teams | |--------------|----------|------------------------| -| 808 | 692 | 42 | +| 810 | 694 | 42 | ### Public API health stats | API Count | Any Count | Missing comments | Missing exports | |--------------|----------|-----------------|--------| -| 49412 | 238 | 37680 | 1886 | +| 49561 | 238 | 37805 | 1888 | ## Plugin Directory @@ -31,7 +31,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibAdvancedSettingsPluginApi" text="advancedSettings"/> | [@elastic/appex-sharedux @elastic/kibana-management](https://github.com/orgs/elastic/teams/appex-sharedux ) | - | 2 | 0 | 2 | 0 | | <DocLink id="kibAiAssistantManagementSelectionPluginApi" text="aiAssistantManagementSelection"/> | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 4 | 0 | 4 | 1 | | <DocLink id="kibAiopsPluginApi" text="aiops"/> | [@elastic/ml-ui](https://github.com/orgs/elastic/teams/ml-ui) | AIOps plugin maintained by ML team. | 72 | 0 | 9 | 2 | -| <DocLink id="kibAlertingPluginApi" text="alerting"/> | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 868 | 1 | 836 | 54 | +| <DocLink id="kibAlertingPluginApi" text="alerting"/> | [@elastic/response-ops](https://github.com/orgs/elastic/teams/response-ops) | - | 868 | 1 | 836 | 52 | | <DocLink id="kibApmPluginApi" text="apm"/> | [@elastic/obs-ux-infra_services-team](https://github.com/orgs/elastic/teams/obs-ux-infra_services-team) | The user interface for Elastic APM | 29 | 0 | 29 | 123 | | <DocLink id="kibApmDataAccessPluginApi" text="apmDataAccess"/> | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 9 | 0 | 9 | 0 | | <DocLink id="kibAssetManagerPluginApi" text="assetManager"/> | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | Asset manager plugin for entity assets (inventory, topology, etc) | 11 | 0 | 11 | 3 | @@ -147,7 +147,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibNewsfeedPluginApi" text="newsfeed"/> | [@elastic/kibana-core](https://github.com/orgs/elastic/teams/kibana-core) | - | 17 | 0 | 17 | 0 | | <DocLink id="kibNoDataPagePluginApi" text="noDataPage"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 3 | 0 | 3 | 0 | | <DocLink id="kibNotificationsPluginApi" text="notifications"/> | [@elastic/appex-sharedux](https://github.com/orgs/elastic/teams/appex-sharedux) | - | 2 | 0 | 2 | 1 | -| <DocLink id="kibObservabilityPluginApi" text="observability"/> | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 705 | 2 | 696 | 16 | +| <DocLink id="kibObservabilityPluginApi" text="observability"/> | [@elastic/obs-ux-management-team](https://github.com/orgs/elastic/teams/obs-ux-management-team) | - | 693 | 2 | 686 | 22 | | <DocLink id="kibObservabilityAIAssistantPluginApi" text="observabilityAIAssistant"/> | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 290 | 1 | 288 | 26 | | <DocLink id="kibObservabilityAIAssistantAppPluginApi" text="observabilityAIAssistantApp"/> | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 4 | 0 | 4 | 0 | | <DocLink id="kibObservabilityAiAssistantManagementPluginApi" text="observabilityAiAssistantManagement"/> | [@elastic/obs-ai-assistant](https://github.com/orgs/elastic/teams/obs-ai-assistant) | - | 2 | 0 | 2 | 0 | @@ -179,7 +179,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibSearchNotebooksPluginApi" text="searchNotebooks"/> | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | Plugin to provide access to and rendering of python notebooks for use in the persistent developer console. | 6 | 0 | 6 | 0 | | <DocLink id="kibSearchPlaygroundPluginApi" text="searchPlayground"/> | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 18 | 0 | 10 | 1 | | searchprofiler | [@elastic/kibana-management](https://github.com/orgs/elastic/teams/kibana-management) | - | 0 | 0 | 0 | 0 | -| <DocLink id="kibSecurityPluginApi" text="security"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 414 | 0 | 205 | 3 | +| <DocLink id="kibSecurityPluginApi" text="security"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | This plugin provides authentication and authorization features, and exposes functionality to understand the capabilities of the currently authenticated user. | 411 | 0 | 204 | 1 | | <DocLink id="kibSecuritySolutionPluginApi" text="securitySolution"/> | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | - | 191 | 0 | 121 | 37 | | <DocLink id="kibSecuritySolutionEssPluginApi" text="securitySolutionEss"/> | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | ESS customizations for Security Solution. | 6 | 0 | 6 | 0 | | <DocLink id="kibSecuritySolutionServerlessPluginApi" text="securitySolutionServerless"/> | [@elastic/security-solution](https://github.com/orgs/elastic/teams/security-solution) | Serverless customizations for security. | 7 | 0 | 7 | 0 | @@ -488,7 +488,7 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnEcsDataQualityDashboardPluginApi" text="@kbn/ecs-data-quality-dashboard"/> | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 13 | 0 | 5 | 0 | | <DocLink id="kibKbnElasticAgentUtilsPluginApi" text="@kbn/elastic-agent-utils"/> | [@elastic/obs-ux-logs-team](https://github.com/orgs/elastic/teams/obs-ux-logs-team) | - | 35 | 0 | 34 | 0 | | <DocLink id="kibKbnElasticAssistantPluginApi" text="@kbn/elastic-assistant"/> | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | - | 165 | 0 | 138 | 9 | -| <DocLink id="kibKbnElasticAssistantCommonPluginApi" text="@kbn/elastic-assistant-common"/> | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | - | 305 | 0 | 286 | 0 | +| <DocLink id="kibKbnElasticAssistantCommonPluginApi" text="@kbn/elastic-assistant-common"/> | [@elastic/security-generative-ai](https://github.com/orgs/elastic/teams/security-generative-ai) | - | 329 | 0 | 307 | 0 | | <DocLink id="kibKbnEntitiesSchemaPluginApi" text="@kbn/entities-schema"/> | [@elastic/obs-knowledge-team](https://github.com/orgs/elastic/teams/obs-knowledge-team) | - | 20 | 0 | 20 | 0 | | <DocLink id="kibKbnEsPluginApi" text="@kbn/es"/> | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 52 | 0 | 37 | 7 | | <DocLink id="kibKbnEsArchiverPluginApi" text="@kbn/es-archiver"/> | [@elastic/kibana-operations](https://github.com/orgs/elastic/teams/kibana-operations) | - | 32 | 0 | 19 | 1 | @@ -637,10 +637,12 @@ tags: ['contributor', 'dev', 'apidocs', 'kibana'] | <DocLink id="kibKbnSearchIndexDocumentsPluginApi" text="@kbn/search-index-documents"/> | [@elastic/search-kibana](https://github.com/orgs/elastic/teams/search-kibana) | - | 25 | 0 | 25 | 0 | | <DocLink id="kibKbnSearchResponseWarningsPluginApi" text="@kbn/search-response-warnings"/> | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 20 | 0 | 18 | 1 | | <DocLink id="kibKbnSearchTypesPluginApi" text="@kbn/search-types"/> | [@elastic/kibana-data-discovery](https://github.com/orgs/elastic/teams/kibana-data-discovery) | - | 50 | 0 | 25 | 0 | +| <DocLink id="kibKbnSecurityApiKeyManagementPluginApi" text="@kbn/security-api-key-management"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 68 | 0 | 65 | 0 | +| <DocLink id="kibKbnSecurityFormComponentsPluginApi" text="@kbn/security-form-components"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 35 | 0 | 25 | 0 | | <DocLink id="kibKbnSecurityHardeningPluginApi" text="@kbn/security-hardening"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 7 | 0 | 7 | 0 | -| <DocLink id="kibKbnSecurityPluginTypesCommonPluginApi" text="@kbn/security-plugin-types-common"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 88 | 0 | 40 | 0 | +| <DocLink id="kibKbnSecurityPluginTypesCommonPluginApi" text="@kbn/security-plugin-types-common"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 116 | 0 | 58 | 0 | | <DocLink id="kibKbnSecurityPluginTypesPublicPluginApi" text="@kbn/security-plugin-types-public"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 51 | 0 | 25 | 0 | -| <DocLink id="kibKbnSecurityPluginTypesServerPluginApi" text="@kbn/security-plugin-types-server"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 207 | 0 | 114 | 0 | +| <DocLink id="kibKbnSecurityPluginTypesServerPluginApi" text="@kbn/security-plugin-types-server"/> | [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana-security) | - | 216 | 0 | 121 | 0 | | <DocLink id="kibKbnSecuritySolutionFeaturesPluginApi" text="@kbn/security-solution-features"/> | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 14 | 0 | 14 | 6 | | <DocLink id="kibKbnSecuritySolutionNavigationPluginApi" text="@kbn/security-solution-navigation"/> | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 54 | 0 | 49 | 0 | | <DocLink id="kibKbnSecuritySolutionSideNavPluginApi" text="@kbn/security-solution-side-nav"/> | [@elastic/security-threat-hunting-explore](https://github.com/orgs/elastic/teams/security-threat-hunting-explore) | - | 30 | 0 | 24 | 0 | diff --git a/api_docs/presentation_panel.mdx b/api_docs/presentation_panel.mdx index b9e7d0c151572..3088517943524 100644 --- a/api_docs/presentation_panel.mdx +++ b/api_docs/presentation_panel.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationPanel title: "presentationPanel" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationPanel plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationPanel'] --- import presentationPanelObj from './presentation_panel.devdocs.json'; diff --git a/api_docs/presentation_util.mdx b/api_docs/presentation_util.mdx index e197eddaa2983..cb7fb8337d696 100644 --- a/api_docs/presentation_util.mdx +++ b/api_docs/presentation_util.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/presentationUtil title: "presentationUtil" image: https://source.unsplash.com/400x175/?github description: API docs for the presentationUtil plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'presentationUtil'] --- import presentationUtilObj from './presentation_util.devdocs.json'; diff --git a/api_docs/profiling.mdx b/api_docs/profiling.mdx index 5e749e2faa87a..9ac528357a45e 100644 --- a/api_docs/profiling.mdx +++ b/api_docs/profiling.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profiling title: "profiling" image: https://source.unsplash.com/400x175/?github description: API docs for the profiling plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profiling'] --- import profilingObj from './profiling.devdocs.json'; diff --git a/api_docs/profiling_data_access.mdx b/api_docs/profiling_data_access.mdx index 368fdf3b34e30..058c13c270255 100644 --- a/api_docs/profiling_data_access.mdx +++ b/api_docs/profiling_data_access.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/profilingDataAccess title: "profilingDataAccess" image: https://source.unsplash.com/400x175/?github description: API docs for the profilingDataAccess plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'profilingDataAccess'] --- import profilingDataAccessObj from './profiling_data_access.devdocs.json'; diff --git a/api_docs/remote_clusters.mdx b/api_docs/remote_clusters.mdx index 1fe7f5657310c..bb368f04afdd1 100644 --- a/api_docs/remote_clusters.mdx +++ b/api_docs/remote_clusters.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/remoteClusters title: "remoteClusters" image: https://source.unsplash.com/400x175/?github description: API docs for the remoteClusters plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'remoteClusters'] --- import remoteClustersObj from './remote_clusters.devdocs.json'; diff --git a/api_docs/reporting.mdx b/api_docs/reporting.mdx index b1474a2d53082..052095317d7e4 100644 --- a/api_docs/reporting.mdx +++ b/api_docs/reporting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/reporting title: "reporting" image: https://source.unsplash.com/400x175/?github description: API docs for the reporting plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'reporting'] --- import reportingObj from './reporting.devdocs.json'; diff --git a/api_docs/rollup.mdx b/api_docs/rollup.mdx index e1204a8520125..6566456c6e407 100644 --- a/api_docs/rollup.mdx +++ b/api_docs/rollup.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/rollup title: "rollup" image: https://source.unsplash.com/400x175/?github description: API docs for the rollup plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'rollup'] --- import rollupObj from './rollup.devdocs.json'; diff --git a/api_docs/rule_registry.mdx b/api_docs/rule_registry.mdx index 6d5d5304b05ec..c46010826a24c 100644 --- a/api_docs/rule_registry.mdx +++ b/api_docs/rule_registry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ruleRegistry title: "ruleRegistry" image: https://source.unsplash.com/400x175/?github description: API docs for the ruleRegistry plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ruleRegistry'] --- import ruleRegistryObj from './rule_registry.devdocs.json'; diff --git a/api_docs/runtime_fields.mdx b/api_docs/runtime_fields.mdx index 03211d7d7f21e..b84e84df42452 100644 --- a/api_docs/runtime_fields.mdx +++ b/api_docs/runtime_fields.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/runtimeFields title: "runtimeFields" image: https://source.unsplash.com/400x175/?github description: API docs for the runtimeFields plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'runtimeFields'] --- import runtimeFieldsObj from './runtime_fields.devdocs.json'; diff --git a/api_docs/saved_objects.mdx b/api_docs/saved_objects.mdx index d6c60152562b5..18d1a9cdbcfeb 100644 --- a/api_docs/saved_objects.mdx +++ b/api_docs/saved_objects.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjects title: "savedObjects" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjects plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjects'] --- import savedObjectsObj from './saved_objects.devdocs.json'; diff --git a/api_docs/saved_objects_finder.mdx b/api_docs/saved_objects_finder.mdx index ccb6391122f19..b24d73b362c2b 100644 --- a/api_docs/saved_objects_finder.mdx +++ b/api_docs/saved_objects_finder.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsFinder title: "savedObjectsFinder" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsFinder plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsFinder'] --- import savedObjectsFinderObj from './saved_objects_finder.devdocs.json'; diff --git a/api_docs/saved_objects_management.mdx b/api_docs/saved_objects_management.mdx index 5981e5b9bc1fd..91235a1d0044c 100644 --- a/api_docs/saved_objects_management.mdx +++ b/api_docs/saved_objects_management.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsManagement title: "savedObjectsManagement" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsManagement plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsManagement'] --- import savedObjectsManagementObj from './saved_objects_management.devdocs.json'; diff --git a/api_docs/saved_objects_tagging.mdx b/api_docs/saved_objects_tagging.mdx index 740773dd26207..25cf532cfc37e 100644 --- a/api_docs/saved_objects_tagging.mdx +++ b/api_docs/saved_objects_tagging.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTagging title: "savedObjectsTagging" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTagging plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTagging'] --- import savedObjectsTaggingObj from './saved_objects_tagging.devdocs.json'; diff --git a/api_docs/saved_objects_tagging_oss.mdx b/api_docs/saved_objects_tagging_oss.mdx index 8e9fefc97a4c1..997e1bff5c758 100644 --- a/api_docs/saved_objects_tagging_oss.mdx +++ b/api_docs/saved_objects_tagging_oss.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedObjectsTaggingOss title: "savedObjectsTaggingOss" image: https://source.unsplash.com/400x175/?github description: API docs for the savedObjectsTaggingOss plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedObjectsTaggingOss'] --- import savedObjectsTaggingOssObj from './saved_objects_tagging_oss.devdocs.json'; diff --git a/api_docs/saved_search.mdx b/api_docs/saved_search.mdx index ace8f9057ef17..67868c678419e 100644 --- a/api_docs/saved_search.mdx +++ b/api_docs/saved_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/savedSearch title: "savedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the savedSearch plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'savedSearch'] --- import savedSearchObj from './saved_search.devdocs.json'; diff --git a/api_docs/screenshot_mode.mdx b/api_docs/screenshot_mode.mdx index e050cdd04db30..eb0537533306b 100644 --- a/api_docs/screenshot_mode.mdx +++ b/api_docs/screenshot_mode.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotMode title: "screenshotMode" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotMode plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotMode'] --- import screenshotModeObj from './screenshot_mode.devdocs.json'; diff --git a/api_docs/screenshotting.mdx b/api_docs/screenshotting.mdx index 0345229ccd848..49d1d55211ff7 100644 --- a/api_docs/screenshotting.mdx +++ b/api_docs/screenshotting.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/screenshotting title: "screenshotting" image: https://source.unsplash.com/400x175/?github description: API docs for the screenshotting plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'screenshotting'] --- import screenshottingObj from './screenshotting.devdocs.json'; diff --git a/api_docs/search_connectors.mdx b/api_docs/search_connectors.mdx index b91fc2904e34a..c71e2fb7400ba 100644 --- a/api_docs/search_connectors.mdx +++ b/api_docs/search_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchConnectors title: "searchConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the searchConnectors plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchConnectors'] --- import searchConnectorsObj from './search_connectors.devdocs.json'; diff --git a/api_docs/search_homepage.mdx b/api_docs/search_homepage.mdx index 925a69bc38e80..578276dc434e1 100644 --- a/api_docs/search_homepage.mdx +++ b/api_docs/search_homepage.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchHomepage title: "searchHomepage" image: https://source.unsplash.com/400x175/?github description: API docs for the searchHomepage plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchHomepage'] --- import searchHomepageObj from './search_homepage.devdocs.json'; diff --git a/api_docs/search_inference_endpoints.mdx b/api_docs/search_inference_endpoints.mdx index b3eb93fda9b40..37c14e51525d8 100644 --- a/api_docs/search_inference_endpoints.mdx +++ b/api_docs/search_inference_endpoints.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchInferenceEndpoints title: "searchInferenceEndpoints" image: https://source.unsplash.com/400x175/?github description: API docs for the searchInferenceEndpoints plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchInferenceEndpoints'] --- import searchInferenceEndpointsObj from './search_inference_endpoints.devdocs.json'; diff --git a/api_docs/search_notebooks.mdx b/api_docs/search_notebooks.mdx index 6a4f5b8aa94af..95306ad478d0e 100644 --- a/api_docs/search_notebooks.mdx +++ b/api_docs/search_notebooks.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchNotebooks title: "searchNotebooks" image: https://source.unsplash.com/400x175/?github description: API docs for the searchNotebooks plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchNotebooks'] --- import searchNotebooksObj from './search_notebooks.devdocs.json'; diff --git a/api_docs/search_playground.mdx b/api_docs/search_playground.mdx index dd449fe68a986..df2fc5bb91e20 100644 --- a/api_docs/search_playground.mdx +++ b/api_docs/search_playground.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/searchPlayground title: "searchPlayground" image: https://source.unsplash.com/400x175/?github description: API docs for the searchPlayground plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'searchPlayground'] --- import searchPlaygroundObj from './search_playground.devdocs.json'; diff --git a/api_docs/security.devdocs.json b/api_docs/security.devdocs.json index 9896e29ee043a..8511554e9b273 100644 --- a/api_docs/security.devdocs.json +++ b/api_docs/security.devdocs.json @@ -1255,16 +1255,7 @@ "path": "x-pack/packages/security/plugin_types_public/src/plugin.ts", "deprecated": true, "trackAdoption": false, - "references": [ - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/common/components/filebeat_config_flyout/filebeat_config_flyout.tsx" - }, - { - "plugin": "dataVisualizer", - "path": "x-pack/plugins/data_visualizer/public/application/index_data_visualizer/hooks/use_data_visualizer_grid_data.ts" - } - ] + "references": [] }, { "parentPluginId": "security", @@ -6623,47 +6614,6 @@ ], "initialIsOpen": false }, - { - "parentPluginId": "security", - "id": "def-common.RestApiKey", - "type": "Interface", - "tags": [], - "label": "RestApiKey", - "description": [ - "\nInterface representing a REST API key the way it is returned by Elasticsearch GET endpoint.\n\nTODO: Remove this type when `@elastic/elasticsearch` has been updated." - ], - "signature": [ - { - "pluginId": "security", - "scope": "common", - "docId": "kibSecurityPluginApi", - "section": "def-common.RestApiKey", - "text": "RestApiKey" - }, - " extends ", - "BaseApiKey" - ], - "path": "x-pack/plugins/security/common/model/api_key.ts", - "deprecated": false, - "trackAdoption": false, - "children": [ - { - "parentPluginId": "security", - "id": "def-common.RestApiKey.type", - "type": "string", - "tags": [], - "label": "type", - "description": [], - "signature": [ - "\"rest\"" - ], - "path": "x-pack/plugins/security/common/model/api_key.ts", - "deprecated": false, - "trackAdoption": false - } - ], - "initialIsOpen": false - }, { "parentPluginId": "security", "id": "def-common.Role", @@ -7980,31 +7930,6 @@ ], "enums": [], "misc": [ - { - "parentPluginId": "security", - "id": "def-common.ApiKey", - "type": "Type", - "tags": [], - "label": "ApiKey", - "description": [ - "\nInterface representing an API key the way it is returned by Elasticsearch GET endpoint." - ], - "signature": [ - { - "pluginId": "security", - "scope": "common", - "docId": "kibSecurityPluginApi", - "section": "def-common.RestApiKey", - "text": "RestApiKey" - }, - " | ", - "CrossClusterApiKey" - ], - "path": "x-pack/plugins/security/common/model/api_key.ts", - "deprecated": false, - "trackAdoption": false, - "initialIsOpen": false - }, { "parentPluginId": "security", "id": "def-common.LoginLayout", diff --git a/api_docs/security.mdx b/api_docs/security.mdx index fde376dd1ce21..372667ec3823f 100644 --- a/api_docs/security.mdx +++ b/api_docs/security.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/security title: "security" image: https://source.unsplash.com/400x175/?github description: API docs for the security plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'security'] --- import securityObj from './security.devdocs.json'; @@ -21,7 +21,7 @@ Contact [@elastic/kibana-security](https://github.com/orgs/elastic/teams/kibana- | Public API count | Any count | Items lacking comments | Missing exports | |-------------------|-----------|------------------------|-----------------| -| 414 | 0 | 205 | 3 | +| 411 | 0 | 204 | 1 | ## Client diff --git a/api_docs/security_solution.mdx b/api_docs/security_solution.mdx index 887684bdf4edc..b2201135f5ed4 100644 --- a/api_docs/security_solution.mdx +++ b/api_docs/security_solution.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolution title: "securitySolution" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolution plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolution'] --- import securitySolutionObj from './security_solution.devdocs.json'; diff --git a/api_docs/security_solution_ess.mdx b/api_docs/security_solution_ess.mdx index 634b7a2fda3b3..8b71da2715c23 100644 --- a/api_docs/security_solution_ess.mdx +++ b/api_docs/security_solution_ess.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionEss title: "securitySolutionEss" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionEss plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionEss'] --- import securitySolutionEssObj from './security_solution_ess.devdocs.json'; diff --git a/api_docs/security_solution_serverless.mdx b/api_docs/security_solution_serverless.mdx index b9a3f691b70f1..2a769f0669dd3 100644 --- a/api_docs/security_solution_serverless.mdx +++ b/api_docs/security_solution_serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/securitySolutionServerless title: "securitySolutionServerless" image: https://source.unsplash.com/400x175/?github description: API docs for the securitySolutionServerless plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'securitySolutionServerless'] --- import securitySolutionServerlessObj from './security_solution_serverless.devdocs.json'; diff --git a/api_docs/serverless.mdx b/api_docs/serverless.mdx index 872eedbfec118..c79c1e206d08e 100644 --- a/api_docs/serverless.mdx +++ b/api_docs/serverless.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverless title: "serverless" image: https://source.unsplash.com/400x175/?github description: API docs for the serverless plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverless'] --- import serverlessObj from './serverless.devdocs.json'; diff --git a/api_docs/serverless_observability.mdx b/api_docs/serverless_observability.mdx index f8070afa28d9e..2b2524b152444 100644 --- a/api_docs/serverless_observability.mdx +++ b/api_docs/serverless_observability.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessObservability title: "serverlessObservability" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessObservability plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessObservability'] --- import serverlessObservabilityObj from './serverless_observability.devdocs.json'; diff --git a/api_docs/serverless_search.mdx b/api_docs/serverless_search.mdx index a084d33659da1..269c75104ac33 100644 --- a/api_docs/serverless_search.mdx +++ b/api_docs/serverless_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/serverlessSearch title: "serverlessSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the serverlessSearch plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'serverlessSearch'] --- import serverlessSearchObj from './serverless_search.devdocs.json'; diff --git a/api_docs/session_view.mdx b/api_docs/session_view.mdx index 7cc8ff8cc077c..cb30d987cd745 100644 --- a/api_docs/session_view.mdx +++ b/api_docs/session_view.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/sessionView title: "sessionView" image: https://source.unsplash.com/400x175/?github description: API docs for the sessionView plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'sessionView'] --- import sessionViewObj from './session_view.devdocs.json'; diff --git a/api_docs/share.mdx b/api_docs/share.mdx index f59df61a3f6f7..b7aaab1fadce0 100644 --- a/api_docs/share.mdx +++ b/api_docs/share.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/share title: "share" image: https://source.unsplash.com/400x175/?github description: API docs for the share plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'share'] --- import shareObj from './share.devdocs.json'; diff --git a/api_docs/slo.mdx b/api_docs/slo.mdx index cbe568db4c544..fd15d4bf79c76 100644 --- a/api_docs/slo.mdx +++ b/api_docs/slo.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/slo title: "slo" image: https://source.unsplash.com/400x175/?github description: API docs for the slo plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'slo'] --- import sloObj from './slo.devdocs.json'; diff --git a/api_docs/snapshot_restore.mdx b/api_docs/snapshot_restore.mdx index 0dcc86139743a..5b43cf0a1a897 100644 --- a/api_docs/snapshot_restore.mdx +++ b/api_docs/snapshot_restore.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/snapshotRestore title: "snapshotRestore" image: https://source.unsplash.com/400x175/?github description: API docs for the snapshotRestore plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'snapshotRestore'] --- import snapshotRestoreObj from './snapshot_restore.devdocs.json'; diff --git a/api_docs/spaces.mdx b/api_docs/spaces.mdx index 76b5a1a3aaf53..94a30d9d19f54 100644 --- a/api_docs/spaces.mdx +++ b/api_docs/spaces.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/spaces title: "spaces" image: https://source.unsplash.com/400x175/?github description: API docs for the spaces plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'spaces'] --- import spacesObj from './spaces.devdocs.json'; diff --git a/api_docs/stack_alerts.mdx b/api_docs/stack_alerts.mdx index 5ca2df3020adb..35f20eb4d194e 100644 --- a/api_docs/stack_alerts.mdx +++ b/api_docs/stack_alerts.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackAlerts title: "stackAlerts" image: https://source.unsplash.com/400x175/?github description: API docs for the stackAlerts plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackAlerts'] --- import stackAlertsObj from './stack_alerts.devdocs.json'; diff --git a/api_docs/stack_connectors.mdx b/api_docs/stack_connectors.mdx index 72c81084f19fa..e1d92eca17256 100644 --- a/api_docs/stack_connectors.mdx +++ b/api_docs/stack_connectors.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/stackConnectors title: "stackConnectors" image: https://source.unsplash.com/400x175/?github description: API docs for the stackConnectors plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'stackConnectors'] --- import stackConnectorsObj from './stack_connectors.devdocs.json'; diff --git a/api_docs/task_manager.mdx b/api_docs/task_manager.mdx index ed349d0cd8b6e..0741b5ed6bbaa 100644 --- a/api_docs/task_manager.mdx +++ b/api_docs/task_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/taskManager title: "taskManager" image: https://source.unsplash.com/400x175/?github description: API docs for the taskManager plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'taskManager'] --- import taskManagerObj from './task_manager.devdocs.json'; diff --git a/api_docs/telemetry.mdx b/api_docs/telemetry.mdx index 9938a533875ab..abf3e0319ed0c 100644 --- a/api_docs/telemetry.mdx +++ b/api_docs/telemetry.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetry title: "telemetry" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetry plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetry'] --- import telemetryObj from './telemetry.devdocs.json'; diff --git a/api_docs/telemetry_collection_manager.mdx b/api_docs/telemetry_collection_manager.mdx index 1123feb2b28c6..d2367dca904c0 100644 --- a/api_docs/telemetry_collection_manager.mdx +++ b/api_docs/telemetry_collection_manager.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionManager title: "telemetryCollectionManager" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionManager plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionManager'] --- import telemetryCollectionManagerObj from './telemetry_collection_manager.devdocs.json'; diff --git a/api_docs/telemetry_collection_xpack.mdx b/api_docs/telemetry_collection_xpack.mdx index 653ee5652d926..444f5b25a7737 100644 --- a/api_docs/telemetry_collection_xpack.mdx +++ b/api_docs/telemetry_collection_xpack.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryCollectionXpack title: "telemetryCollectionXpack" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryCollectionXpack plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryCollectionXpack'] --- import telemetryCollectionXpackObj from './telemetry_collection_xpack.devdocs.json'; diff --git a/api_docs/telemetry_management_section.mdx b/api_docs/telemetry_management_section.mdx index 2e284c4884d84..36bdb33aaae9d 100644 --- a/api_docs/telemetry_management_section.mdx +++ b/api_docs/telemetry_management_section.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/telemetryManagementSection title: "telemetryManagementSection" image: https://source.unsplash.com/400x175/?github description: API docs for the telemetryManagementSection plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'telemetryManagementSection'] --- import telemetryManagementSectionObj from './telemetry_management_section.devdocs.json'; diff --git a/api_docs/text_based_languages.mdx b/api_docs/text_based_languages.mdx index 50b035e5aa10a..1ffe28521c2b2 100644 --- a/api_docs/text_based_languages.mdx +++ b/api_docs/text_based_languages.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/textBasedLanguages title: "textBasedLanguages" image: https://source.unsplash.com/400x175/?github description: API docs for the textBasedLanguages plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'textBasedLanguages'] --- import textBasedLanguagesObj from './text_based_languages.devdocs.json'; diff --git a/api_docs/threat_intelligence.mdx b/api_docs/threat_intelligence.mdx index 5cf667ea05cbb..1e7710286a01e 100644 --- a/api_docs/threat_intelligence.mdx +++ b/api_docs/threat_intelligence.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/threatIntelligence title: "threatIntelligence" image: https://source.unsplash.com/400x175/?github description: API docs for the threatIntelligence plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'threatIntelligence'] --- import threatIntelligenceObj from './threat_intelligence.devdocs.json'; diff --git a/api_docs/timelines.mdx b/api_docs/timelines.mdx index 93236e324fa3f..6c2c424cc639e 100644 --- a/api_docs/timelines.mdx +++ b/api_docs/timelines.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/timelines title: "timelines" image: https://source.unsplash.com/400x175/?github description: API docs for the timelines plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'timelines'] --- import timelinesObj from './timelines.devdocs.json'; diff --git a/api_docs/transform.mdx b/api_docs/transform.mdx index 1ddc4fcfb16ff..66022f4afcc65 100644 --- a/api_docs/transform.mdx +++ b/api_docs/transform.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/transform title: "transform" image: https://source.unsplash.com/400x175/?github description: API docs for the transform plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'transform'] --- import transformObj from './transform.devdocs.json'; diff --git a/api_docs/triggers_actions_ui.mdx b/api_docs/triggers_actions_ui.mdx index c1795abdcb2e4..aafca4662428b 100644 --- a/api_docs/triggers_actions_ui.mdx +++ b/api_docs/triggers_actions_ui.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/triggersActionsUi title: "triggersActionsUi" image: https://source.unsplash.com/400x175/?github description: API docs for the triggersActionsUi plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'triggersActionsUi'] --- import triggersActionsUiObj from './triggers_actions_ui.devdocs.json'; diff --git a/api_docs/ui_actions.mdx b/api_docs/ui_actions.mdx index 79cec7c3ee5c4..057cb5ee6e384 100644 --- a/api_docs/ui_actions.mdx +++ b/api_docs/ui_actions.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActions title: "uiActions" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActions plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActions'] --- import uiActionsObj from './ui_actions.devdocs.json'; diff --git a/api_docs/ui_actions_enhanced.mdx b/api_docs/ui_actions_enhanced.mdx index 4008aba47b7ce..8b394d1ca1412 100644 --- a/api_docs/ui_actions_enhanced.mdx +++ b/api_docs/ui_actions_enhanced.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uiActionsEnhanced title: "uiActionsEnhanced" image: https://source.unsplash.com/400x175/?github description: API docs for the uiActionsEnhanced plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uiActionsEnhanced'] --- import uiActionsEnhancedObj from './ui_actions_enhanced.devdocs.json'; diff --git a/api_docs/unified_doc_viewer.mdx b/api_docs/unified_doc_viewer.mdx index 5a3f485e875a9..57fdca0443572 100644 --- a/api_docs/unified_doc_viewer.mdx +++ b/api_docs/unified_doc_viewer.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedDocViewer title: "unifiedDocViewer" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedDocViewer plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedDocViewer'] --- import unifiedDocViewerObj from './unified_doc_viewer.devdocs.json'; diff --git a/api_docs/unified_histogram.mdx b/api_docs/unified_histogram.mdx index 54d92fc2aba81..946f8cd0c8173 100644 --- a/api_docs/unified_histogram.mdx +++ b/api_docs/unified_histogram.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedHistogram title: "unifiedHistogram" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedHistogram plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedHistogram'] --- import unifiedHistogramObj from './unified_histogram.devdocs.json'; diff --git a/api_docs/unified_search.mdx b/api_docs/unified_search.mdx index 6990f96af5bd9..ecd69631eb8a2 100644 --- a/api_docs/unified_search.mdx +++ b/api_docs/unified_search.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch title: "unifiedSearch" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch'] --- import unifiedSearchObj from './unified_search.devdocs.json'; diff --git a/api_docs/unified_search_autocomplete.mdx b/api_docs/unified_search_autocomplete.mdx index d1ed759c90b48..c5bca47ad5d0c 100644 --- a/api_docs/unified_search_autocomplete.mdx +++ b/api_docs/unified_search_autocomplete.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/unifiedSearch-autocomplete title: "unifiedSearch.autocomplete" image: https://source.unsplash.com/400x175/?github description: API docs for the unifiedSearch.autocomplete plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'unifiedSearch.autocomplete'] --- import unifiedSearchAutocompleteObj from './unified_search_autocomplete.devdocs.json'; diff --git a/api_docs/uptime.mdx b/api_docs/uptime.mdx index 2581ca3d986d7..437dccb7649a7 100644 --- a/api_docs/uptime.mdx +++ b/api_docs/uptime.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/uptime title: "uptime" image: https://source.unsplash.com/400x175/?github description: API docs for the uptime plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'uptime'] --- import uptimeObj from './uptime.devdocs.json'; diff --git a/api_docs/url_forwarding.mdx b/api_docs/url_forwarding.mdx index e6cb90ae31a37..56953555e1660 100644 --- a/api_docs/url_forwarding.mdx +++ b/api_docs/url_forwarding.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/urlForwarding title: "urlForwarding" image: https://source.unsplash.com/400x175/?github description: API docs for the urlForwarding plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'urlForwarding'] --- import urlForwardingObj from './url_forwarding.devdocs.json'; diff --git a/api_docs/usage_collection.mdx b/api_docs/usage_collection.mdx index c7345789d14b3..304ad99301db7 100644 --- a/api_docs/usage_collection.mdx +++ b/api_docs/usage_collection.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/usageCollection title: "usageCollection" image: https://source.unsplash.com/400x175/?github description: API docs for the usageCollection plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'usageCollection'] --- import usageCollectionObj from './usage_collection.devdocs.json'; diff --git a/api_docs/ux.mdx b/api_docs/ux.mdx index 6eb4196ccf5a4..0699b0c2bb804 100644 --- a/api_docs/ux.mdx +++ b/api_docs/ux.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/ux title: "ux" image: https://source.unsplash.com/400x175/?github description: API docs for the ux plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'ux'] --- import uxObj from './ux.devdocs.json'; diff --git a/api_docs/vis_default_editor.mdx b/api_docs/vis_default_editor.mdx index 3266c1af8d2db..1e8fc23a4ac33 100644 --- a/api_docs/vis_default_editor.mdx +++ b/api_docs/vis_default_editor.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visDefaultEditor title: "visDefaultEditor" image: https://source.unsplash.com/400x175/?github description: API docs for the visDefaultEditor plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visDefaultEditor'] --- import visDefaultEditorObj from './vis_default_editor.devdocs.json'; diff --git a/api_docs/vis_type_gauge.mdx b/api_docs/vis_type_gauge.mdx index e06b9632fa6ce..5191df04916be 100644 --- a/api_docs/vis_type_gauge.mdx +++ b/api_docs/vis_type_gauge.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeGauge title: "visTypeGauge" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeGauge plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeGauge'] --- import visTypeGaugeObj from './vis_type_gauge.devdocs.json'; diff --git a/api_docs/vis_type_heatmap.mdx b/api_docs/vis_type_heatmap.mdx index 95259dd6a3644..89bf2ba455cf4 100644 --- a/api_docs/vis_type_heatmap.mdx +++ b/api_docs/vis_type_heatmap.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeHeatmap title: "visTypeHeatmap" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeHeatmap plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeHeatmap'] --- import visTypeHeatmapObj from './vis_type_heatmap.devdocs.json'; diff --git a/api_docs/vis_type_pie.mdx b/api_docs/vis_type_pie.mdx index 8662a6b3435d3..063094b54475d 100644 --- a/api_docs/vis_type_pie.mdx +++ b/api_docs/vis_type_pie.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypePie title: "visTypePie" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypePie plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypePie'] --- import visTypePieObj from './vis_type_pie.devdocs.json'; diff --git a/api_docs/vis_type_table.mdx b/api_docs/vis_type_table.mdx index efe6e361f5a6e..f2f6e48bea358 100644 --- a/api_docs/vis_type_table.mdx +++ b/api_docs/vis_type_table.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTable title: "visTypeTable" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTable plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTable'] --- import visTypeTableObj from './vis_type_table.devdocs.json'; diff --git a/api_docs/vis_type_timelion.mdx b/api_docs/vis_type_timelion.mdx index a652aa9e61a41..ed98c3f3917cd 100644 --- a/api_docs/vis_type_timelion.mdx +++ b/api_docs/vis_type_timelion.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimelion title: "visTypeTimelion" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimelion plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimelion'] --- import visTypeTimelionObj from './vis_type_timelion.devdocs.json'; diff --git a/api_docs/vis_type_timeseries.mdx b/api_docs/vis_type_timeseries.mdx index 25e6e407040a2..1c8541f3b080a 100644 --- a/api_docs/vis_type_timeseries.mdx +++ b/api_docs/vis_type_timeseries.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeTimeseries title: "visTypeTimeseries" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeTimeseries plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeTimeseries'] --- import visTypeTimeseriesObj from './vis_type_timeseries.devdocs.json'; diff --git a/api_docs/vis_type_vega.mdx b/api_docs/vis_type_vega.mdx index 36dfa8e37ce74..b4f8361136794 100644 --- a/api_docs/vis_type_vega.mdx +++ b/api_docs/vis_type_vega.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVega title: "visTypeVega" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVega plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVega'] --- import visTypeVegaObj from './vis_type_vega.devdocs.json'; diff --git a/api_docs/vis_type_vislib.mdx b/api_docs/vis_type_vislib.mdx index bf659a5d22c89..25aca6964fd65 100644 --- a/api_docs/vis_type_vislib.mdx +++ b/api_docs/vis_type_vislib.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeVislib title: "visTypeVislib" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeVislib plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeVislib'] --- import visTypeVislibObj from './vis_type_vislib.devdocs.json'; diff --git a/api_docs/vis_type_xy.mdx b/api_docs/vis_type_xy.mdx index 9594fd0ad5e0c..53fe17e61d26d 100644 --- a/api_docs/vis_type_xy.mdx +++ b/api_docs/vis_type_xy.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visTypeXy title: "visTypeXy" image: https://source.unsplash.com/400x175/?github description: API docs for the visTypeXy plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visTypeXy'] --- import visTypeXyObj from './vis_type_xy.devdocs.json'; diff --git a/api_docs/visualizations.mdx b/api_docs/visualizations.mdx index cbf9728e310d1..e9c2635558bdf 100644 --- a/api_docs/visualizations.mdx +++ b/api_docs/visualizations.mdx @@ -8,7 +8,7 @@ slug: /kibana-dev-docs/api/visualizations title: "visualizations" image: https://source.unsplash.com/400x175/?github description: API docs for the visualizations plugin -date: 2024-06-25 +date: 2024-06-26 tags: ['contributor', 'dev', 'apidocs', 'kibana', 'visualizations'] --- import visualizationsObj from './visualizations.devdocs.json'; From 4468ce52c373eac076d3f25e71d7697fab467431 Mon Sep 17 00:00:00 2001 From: Mykola Harmash <mykola.harmash@gmail.com> Date: Wed, 26 Jun 2024 09:18:55 +0200 Subject: [PATCH 20/22] [Onboarding] Fix failing Cypress tests (#186898) ## Summary Fixes [failng Cypress tests](https://buildkite.com/elastic/kibana-pull-request/builds/217616#01904f09-ffdb-4ef4-8cc4-84ed91834b25) by adding a payload with required `agentId` to 'ea-status': 'complete' progress step. --- .../logs/custom_logs/install_elastic_agent.cy.ts | 16 ++++++++++++---- .../e2e/cypress/e2e/logs/system_logs.cy.ts | 16 ++++++++++++---- .../e2e/cypress/support/commands.ts | 12 +++++++++++- .../e2e/cypress/support/types.d.ts | 3 ++- 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/install_elastic_agent.cy.ts b/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/install_elastic_agent.cy.ts index 7e0b829e67305..b4707350948f0 100644 --- a/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/install_elastic_agent.cy.ts +++ b/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/e2e/logs/custom_logs/install_elastic_agent.cy.ts @@ -261,7 +261,9 @@ describe('[Logs onboarding] Custom logs - install elastic agent', () => { }); it('shows a success callout when elastic agent status is healthy', () => { - cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete'); + cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', { + agentId: 'test-agent-id', + }); cy.getByTestSubj('obltOnboardingStepStatus-complete') .contains('Connected to the Elastic Agent') .should('exist'); @@ -299,7 +301,9 @@ describe('[Logs onboarding] Custom logs - install elastic agent', () => { cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete'); - cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete'); + cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', { + agentId: 'test-agent-id', + }); }); it('shows loading callout when config is being downloaded to the host', () => { @@ -340,7 +344,9 @@ describe('[Logs onboarding] Custom logs - install elastic agent', () => { cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete'); - cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete'); + cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', { + agentId: 'test-agent-id', + }); }); it('shows loading callout when config is being downloaded to the host', () => { @@ -424,7 +430,9 @@ describe('[Logs onboarding] Custom logs - install elastic agent', () => { cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete'); - cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete'); + cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', { + agentId: 'test-agent-id', + }); cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete'); }); diff --git a/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/e2e/logs/system_logs.cy.ts b/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/e2e/logs/system_logs.cy.ts index 811d073855350..bd0af6f595b34 100644 --- a/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/e2e/logs/system_logs.cy.ts +++ b/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/e2e/logs/system_logs.cy.ts @@ -291,7 +291,9 @@ describe('[Logs onboarding] System logs', () => { }); it('shows a success callout when elastic agent status is healthy', () => { - cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete'); + cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', { + agentId: 'test-agent-id', + }); cy.getByTestSubj('obltOnboardingStepStatus-complete') .contains('Connected to the Elastic Agent') .should('exist'); @@ -330,7 +332,9 @@ describe('[Logs onboarding] System logs', () => { cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete'); - cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete'); + cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', { + agentId: 'test-agent-id', + }); }); it('shows loading callout when config is being downloaded to the host', () => { @@ -371,7 +375,9 @@ describe('[Logs onboarding] System logs', () => { cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete'); - cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete'); + cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', { + agentId: 'test-agent-id', + }); }); it('shows loading callout when config is being downloaded to the host', () => { @@ -456,7 +462,9 @@ describe('[Logs onboarding] System logs', () => { cy.updateInstallationStepStatus(onboardingId, 'ea-download', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-extract', 'complete'); cy.updateInstallationStepStatus(onboardingId, 'ea-install', 'complete'); - cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete'); + cy.updateInstallationStepStatus(onboardingId, 'ea-status', 'complete', { + agentId: 'test-agent-id', + }); cy.updateInstallationStepStatus(onboardingId, 'ea-config', 'complete'); }); diff --git a/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/support/commands.ts b/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/support/commands.ts index ebf44ed802b39..4b63eaf207d72 100644 --- a/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/support/commands.ts +++ b/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/support/commands.ts @@ -24,6 +24,10 @@ export type InstallationStepStatus = | 'danger' | 'current'; +export interface ElasticAgentStepPayload { + agentId: string; +} + Cypress.Commands.add('loginAsViewerUser', () => { return cy.loginAs({ username: ObservabilityOnboardingUsername.viewerUser, @@ -151,7 +155,12 @@ Cypress.Commands.add('deleteIntegration', (integrationName: string) => { Cypress.Commands.add( 'updateInstallationStepStatus', - (onboardingId: string, step: InstallationStep, status: InstallationStepStatus) => { + ( + onboardingId: string, + step: InstallationStep, + status: InstallationStepStatus, + payload: ElasticAgentStepPayload | undefined + ) => { const kibanaUrl = Cypress.env('KIBANA_URL'); cy.log(onboardingId, step, status); @@ -166,6 +175,7 @@ Cypress.Commands.add( auth: { user: 'editor', pass: 'changeme' }, body: { status, + payload, }, }); } diff --git a/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/support/types.d.ts b/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/support/types.d.ts index dbc28bb442bb9..7bb3549a60e7c 100644 --- a/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/support/types.d.ts +++ b/x-pack/plugins/observability_solution/observability_onboarding/e2e/cypress/support/types.d.ts @@ -22,7 +22,8 @@ declare namespace Cypress { updateInstallationStepStatus( onboardingId: string, step: InstallationStep, - status: InstallationStepStatus + status: InstallationStepStatus, + payload?: ElasticAgentStepPayload ): void; } } From eda351ec3665e9bd6b343cf46feb4ac7045d6145 Mon Sep 17 00:00:00 2001 From: Cristina Amico <criamico@users.noreply.github.com> Date: Wed, 26 Jun 2024 11:19:46 +0200 Subject: [PATCH 21/22] [Fleet] Enable multiple agent policies feature only for Enterprise licences (#186871) ## Summary Enable multiple agent policies feature only for Enterprise licences. I created a central hook to reuse in the UI to avoid repeating the same call everywhere and replaced the calls to `enableReusableIntegrationPolicies` with this new hook. ### Testing - Enable a local enterprise licence ([steps](https://elasticco.atlassian.net/wiki/spaces/PM/pages/46802910/Internal+License+-+X-Pack+and+Endgame)) - Enable flag `enableReusableIntegrationPolicies` - The recent changes for multiple agent policies should be visible in the UI Repeat the steps with any lower licence, the UI changes shouldn't be visible ### Checklist - [ ] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [ ] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../steps/step_select_agent_policy.test.tsx | 13 ++++++----- .../steps/step_select_agent_policy.tsx | 20 +++++++--------- .../edit_package_policy_page/index.test.tsx | 14 +++++++---- .../edit_package_policy_page/index.tsx | 7 +++--- .../detail/policies/package_policies.tsx | 6 ++--- .../package_policy_actions_menu.test.tsx | 17 ++++++++++---- .../package_policy_delete_provider.tsx | 7 +++--- x-pack/plugins/fleet/public/hooks/index.ts | 1 + .../hooks/use_multiple_agent_policies.ts | 23 +++++++++++++++++++ 9 files changed, 71 insertions(+), 37 deletions(-) create mode 100644 x-pack/plugins/fleet/public/hooks/use_multiple_agent_policies.ts diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.test.tsx index c560f3ef53a93..33ff461f7efd5 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.test.tsx @@ -10,12 +10,10 @@ import { act } from '@testing-library/react'; import type { PackageInfo } from '../../../../../../../../common'; -import { ExperimentalFeaturesService } from '../../../../../../../services'; - import type { TestRenderer } from '../../../../../../../mock'; import { createFleetTestRendererMock } from '../../../../../../../mock'; -import { useGetAgentPolicies } from '../../../../../hooks'; +import { useGetAgentPolicies, useMultipleAgentPolicies } from '../../../../../hooks'; import { StepSelectAgentPolicy } from './step_select_agent_policy'; @@ -23,6 +21,7 @@ jest.mock('../../../../../hooks', () => { return { ...jest.requireActual('../../../../../hooks'), useGetAgentPolicies: jest.fn(), + useMultipleAgentPolicies: jest.fn(), useGetOutputs: jest.fn().mockReturnValue({ data: { items: [ @@ -61,6 +60,9 @@ jest.mock('../../../../../hooks', () => { const useGetAgentPoliciesMock = useGetAgentPolicies as jest.MockedFunction< typeof useGetAgentPolicies >; +const useMultipleAgentPoliciesMock = useMultipleAgentPolicies as jest.MockedFunction< + typeof useMultipleAgentPolicies +>; describe('step select agent policy', () => { let testRenderer: TestRenderer; @@ -80,6 +82,7 @@ describe('step select agent policy', () => { beforeEach(() => { testRenderer = createFleetTestRendererMock(); + useMultipleAgentPoliciesMock.mockReturnValue({ canUseMultipleAgentPolicies: false }); updateAgentPoliciesMock.mockReset(); }); @@ -124,9 +127,7 @@ describe('step select agent policy', () => { describe('multiple agent policies', () => { beforeEach(() => { - jest - .spyOn(ExperimentalFeaturesService, 'get') - .mockReturnValue({ enableReusableIntegrationPolicies: true }); + useMultipleAgentPoliciesMock.mockReturnValue({ canUseMultipleAgentPolicies: true }); useGetAgentPoliciesMock.mockReturnValue({ data: { diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx index 0593c8274a22e..f28593d84ef9a 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/components/steps/step_select_agent_policy.tsx @@ -24,11 +24,7 @@ import { import { Error } from '../../../../../components'; import type { AgentPolicy, Output, PackageInfo } from '../../../../../types'; -import { - isPackageLimited, - doesAgentPolicyAlreadyIncludePackage, - ExperimentalFeaturesService, -} from '../../../../../services'; +import { isPackageLimited, doesAgentPolicyAlreadyIncludePackage } from '../../../../../services'; import { useGetAgentPolicies, useGetOutputs, @@ -43,6 +39,8 @@ import { PACKAGE_POLICY_SAVED_OBJECT_TYPE, } from '../../../../../../../../common/constants'; +import { useMultipleAgentPolicies } from '../../../../../hooks'; + import { AgentPolicyMultiSelect } from './components/agent_policy_multi_select'; const AgentPolicyFormRow = styled(EuiFormRow)` @@ -229,7 +227,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ const [selectedAgentPolicyError, setSelectedAgentPolicyError] = useState<Error>(); - const { enableReusableIntegrationPolicies } = ExperimentalFeaturesService.get(); + const { canUseMultipleAgentPolicies } = useMultipleAgentPolicies(); const { isLoading, @@ -289,12 +287,10 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ isFirstLoad && selectedPolicyIds.length === 0 && existingAgentPolicies.length && - (enableReusableIntegrationPolicies - ? agentPolicyMultiOptions.length - : agentPolicyOptions.length) + (canUseMultipleAgentPolicies ? agentPolicyMultiOptions.length : agentPolicyOptions.length) ) { setIsFirstLoad(false); - if (enableReusableIntegrationPolicies) { + if (canUseMultipleAgentPolicies) { const enabledOptions = agentPolicyMultiOptions.filter((option) => !option.disabled); if (enabledOptions.length === 1) { setSelectedPolicyIds([enabledOptions[0].key!]); @@ -313,7 +309,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ }, [ agentPolicyOptions, agentPolicyMultiOptions, - enableReusableIntegrationPolicies, + canUseMultipleAgentPolicies, selectedAgentPolicyIds, selectedPolicyIds, existingAgentPolicies, @@ -424,7 +420,7 @@ export const StepSelectAgentPolicy: React.FunctionComponent<{ ) : null } > - {enableReusableIntegrationPolicies ? ( + {canUseMultipleAgentPolicies ? ( <AgentPolicyMultiSelect isLoading={isLoading || !packageInfo || isLoadingSelectedAgentPolicies} selectedPolicyIds={selectedPolicyIds} diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx index f00ac0981cd03..7d50d3e494dbb 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.test.tsx @@ -8,8 +8,6 @@ import React from 'react'; import { fireEvent, act, waitFor } from '@testing-library/react'; -import { ExperimentalFeaturesService } from '../../../../../services'; - import type { TestRenderer } from '../../../../../mock'; import { createFleetTestRendererMock } from '../../../../../mock'; @@ -24,6 +22,7 @@ import { sendCreateAgentPolicy, sendBulkGetAgentPolicies, useGetAgentPolicies, + useMultipleAgentPolicies, } from '../../../hooks'; import { useGetOnePackagePolicy } from '../../../../integrations/hooks'; @@ -39,6 +38,7 @@ jest.mock('../../../hooks', () => { sendGetOnePackagePolicy: jest.fn(), sendGetOneAgentPolicy: jest.fn(), sendUpgradePackagePolicyDryRun: jest.fn(), + useMultipleAgentPolicies: jest.fn(), sendGetPackageInfoByKey: jest.fn().mockImplementation((name, version) => Promise.resolve({ data: { @@ -201,6 +201,10 @@ const TestComponent = async () => { }; }; +const useMultipleAgentPoliciesMock = useMultipleAgentPolicies as jest.MockedFunction< + typeof useMultipleAgentPolicies +>; + describe('edit package policy page', () => { let testRenderer: TestRenderer; let renderResult: ReturnType<typeof testRenderer.render>; @@ -250,6 +254,7 @@ describe('edit package policy page', () => { isLoading: false, resendRequest: jest.fn(), }); + useMultipleAgentPoliciesMock.mockReturnValue({ canUseMultipleAgentPolicies: false }); }); it('should disable submit button on invalid form with empty package var', async () => { @@ -486,9 +491,8 @@ describe('edit package policy page', () => { describe('modify agent policies', () => { beforeEach(() => { - jest - .spyOn(ExperimentalFeaturesService, 'get') - .mockReturnValue({ enableReusableIntegrationPolicies: true }); + useMultipleAgentPoliciesMock.mockReturnValue({ canUseMultipleAgentPolicies: true }); + (sendGetAgentStatus as jest.MockedFunction<any>).mockResolvedValue({ data: { results: { total: 0 } }, }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx index 73e1a9cf8c137..15928ab8bc133 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx @@ -50,13 +50,14 @@ import { import { AGENTLESS_POLICY_ID } from '../../../../../../common/constants'; import type { AgentPolicy, PackagePolicyEditExtensionComponentProps } from '../../../types'; -import { ExperimentalFeaturesService, pkgKeyFromPackageInfo } from '../../../services'; +import { pkgKeyFromPackageInfo } from '../../../services'; import { getInheritedNamespace, getRootPrivilegedDataStreams, isRootPrivilegesRequired, } from '../../../../../../common/services'; +import { useMultipleAgentPolicies } from '../../../hooks'; import { RootPrivilegesCallout } from '../create_package_policy_page/single_page_layout/root_callout'; @@ -103,7 +104,7 @@ export const EditPackagePolicyForm = memo<{ agents: { enabled: isFleetEnabled }, } = useConfig(); const { getHref } = useLink(); - const { enableReusableIntegrationPolicies } = ExperimentalFeaturesService.get(); + const { canUseMultipleAgentPolicies } = useMultipleAgentPolicies(); const { // data @@ -520,7 +521,7 @@ export const EditPackagePolicyForm = memo<{ <EuiSpacer size="xxl" /> </> )} - {enableReusableIntegrationPolicies ? ( + {canUseMultipleAgentPolicies ? ( <StepsWithLessPadding steps={steps} /> ) : ( replaceConfigurePackage || configurePackage diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx index 6e1ce1cf8b2d4..d33958c5a68ec 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/policies/package_policies.tsx @@ -21,7 +21,6 @@ import { i18n } from '@kbn/i18n'; import { FormattedRelative, FormattedMessage } from '@kbn/i18n-react'; import { policyHasFleetServer } from '../../../../../../../../common/services'; -import { ExperimentalFeaturesService } from '../../../../../services'; import { InstallStatus } from '../../../../../types'; import type { GetAgentPoliciesResponseItem, InMemoryPackagePolicy } from '../../../../../types'; @@ -44,6 +43,7 @@ import { import { PackagePolicyAgentsCell } from './components/package_policy_agents_cell'; import { usePackagePoliciesWithAgentPolicy } from './use_package_policies_with_agent_policy'; import { Persona } from './persona'; +import { useMultipleAgentPolicies } from '../../../../../hooks'; interface PackagePoliciesPanelProps { name: string; @@ -103,7 +103,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps const getPackageInstallStatus = useGetPackageInstallStatus(); const packageInstallStatus = getPackageInstallStatus(name); const { pagination, pageSizeOptions, setPagination } = useUrlPagination(); - const { enableReusableIntegrationPolicies } = ExperimentalFeaturesService.get(); + const { canUseMultipleAgentPolicies } = useMultipleAgentPolicies(); const { data, @@ -173,7 +173,7 @@ export const PackagePoliciesPage = ({ name, version }: PackagePoliciesPanelProps [setPagination] ); const canShowMultiplePoliciesCell = - enableReusableIntegrationPolicies && canReadIntegrationPolicies && canReadAgentPolicies; + canUseMultipleAgentPolicies && canReadIntegrationPolicies && canReadAgentPolicies; const columns: Array<EuiTableFieldDataColumnType<InMemoryPackagePolicyAndAgentPolicy>> = useMemo( () => [ { diff --git a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx index 96849c077f881..e099092b4b863 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_actions_menu.test.tsx @@ -12,10 +12,21 @@ import { act } from '@testing-library/react'; import type { AgentPolicy, InMemoryPackagePolicy } from '../types'; import { createIntegrationsTestRendererMock } from '../mock'; -import { ExperimentalFeaturesService } from '../services'; +import { useMultipleAgentPolicies } from '../hooks'; import { PackagePolicyActionsMenu } from './package_policy_actions_menu'; +jest.mock('../hooks', () => { + return { + ...jest.requireActual('../hooks'), + useMultipleAgentPolicies: jest.fn(), + }; +}); + +const useMultipleAgentPoliciesMock = useMultipleAgentPolicies as jest.MockedFunction< + typeof useMultipleAgentPolicies +>; + function renderMenu({ agentPolicies, packagePolicy, @@ -87,9 +98,7 @@ function createMockPackagePolicy( } describe('PackagePolicyActionsMenu', () => { beforeAll(() => { - jest.spyOn(ExperimentalFeaturesService, 'get').mockReturnValue({ - enableReusableIntegrationPolicies: false, - } as any); + useMultipleAgentPoliciesMock.mockReturnValue({ canUseMultipleAgentPolicies: false }); }); it('Should disable upgrade button if package does not have upgrade', async () => { diff --git a/x-pack/plugins/fleet/public/components/package_policy_delete_provider.tsx b/x-pack/plugins/fleet/public/components/package_policy_delete_provider.tsx index c4bdd8a4671fd..35f2313f37e0a 100644 --- a/x-pack/plugins/fleet/public/components/package_policy_delete_provider.tsx +++ b/x-pack/plugins/fleet/public/components/package_policy_delete_provider.tsx @@ -10,11 +10,10 @@ import { EuiCallOut, EuiConfirmModal, EuiSpacer, EuiIconTip } from '@elastic/eui import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import { ExperimentalFeaturesService } from '../services'; import { useStartServices, sendDeletePackagePolicy, useConfig } from '../hooks'; import { AGENTS_PREFIX } from '../../common/constants'; import type { AgentPolicy } from '../types'; -import { sendGetAgents } from '../hooks'; +import { sendGetAgents, useMultipleAgentPolicies } from '../hooks'; interface Props { agentPolicies?: AgentPolicy[]; @@ -42,10 +41,10 @@ export const PackagePolicyDeleteProvider: React.FunctionComponent<Props> = ({ const [agentsCount, setAgentsCount] = useState<number>(0); const [isLoading, setIsLoading] = useState<boolean>(false); const onSuccessCallback = useRef<OnSuccessCallback | null>(null); - const { enableReusableIntegrationPolicies } = ExperimentalFeaturesService.get(); + const { canUseMultipleAgentPolicies } = useMultipleAgentPolicies(); const hasMultipleAgentPolicies = - enableReusableIntegrationPolicies && agentPolicies && agentPolicies.length > 1; + canUseMultipleAgentPolicies && agentPolicies && agentPolicies.length > 1; const fetchAgentsCount = useMemo( () => async () => { diff --git a/x-pack/plugins/fleet/public/hooks/index.ts b/x-pack/plugins/fleet/public/hooks/index.ts index e9450a975d3b5..f537698897a19 100644 --- a/x-pack/plugins/fleet/public/hooks/index.ts +++ b/x-pack/plugins/fleet/public/hooks/index.ts @@ -34,3 +34,4 @@ export * from './use_fleet_server_standalone'; export * from './use_locator'; export * from './use_agent_version'; export * from './use_fleet_server_agents'; +export * from './use_multiple_agent_policies'; diff --git a/x-pack/plugins/fleet/public/hooks/use_multiple_agent_policies.ts b/x-pack/plugins/fleet/public/hooks/use_multiple_agent_policies.ts new file mode 100644 index 0000000000000..2adf814e8ffba --- /dev/null +++ b/x-pack/plugins/fleet/public/hooks/use_multiple_agent_policies.ts @@ -0,0 +1,23 @@ +/* + * 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 { ExperimentalFeaturesService } from '../services'; + +import { useLicense } from './use_license'; + +export const LICENCE_FOR_MULTIPLE_AGENT_POLICIES = 'enterprise'; + +export function useMultipleAgentPolicies() { + const licenseService = useLicense(); + const { enableReusableIntegrationPolicies } = ExperimentalFeaturesService.get(); + + const hasEnterpriseLicence = licenseService.hasAtLeast(LICENCE_FOR_MULTIPLE_AGENT_POLICIES); + + const canUseMultipleAgentPolicies = enableReusableIntegrationPolicies && hasEnterpriseLicence; + + return { canUseMultipleAgentPolicies }; +} From 1b17f661286a2a7f11df961f455d140bd609b1ea Mon Sep 17 00:00:00 2001 From: Maxim Kholod <maxim.kholod@elastic.co> Date: Wed, 26 Jun 2024 11:26:27 +0200 Subject: [PATCH 22/22] [Cloud Security] unskip"Findings Page - DataTable > Table Sort" FTR test suit (#186825) ## Summary Related to: - https://github.com/elastic/kibana/issues/152913 Unskipping the test, as the data grid has been refactored and it after running flaky test runner it looks like the flakiness is gone (finger crossed, in the failed cases the failures were unrelated, eg. agent lost). --- .../test/cloud_security_posture_functional/pages/findings.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/test/cloud_security_posture_functional/pages/findings.ts b/x-pack/test/cloud_security_posture_functional/pages/findings.ts index 57b9f303a2046..76ea64f6e6195 100644 --- a/x-pack/test/cloud_security_posture_functional/pages/findings.ts +++ b/x-pack/test/cloud_security_posture_functional/pages/findings.ts @@ -147,8 +147,7 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { await findings.index.remove(); }); - // FLAKY: https://github.com/elastic/kibana/issues/152913 - describe.skip('Table Sort', () => { + describe('Table Sort', () => { type SortingMethod = (a: string, b: string) => number; type SortDirection = 'asc' | 'desc'; // Sort by lexical order will sort by the first character of the string (case-sensitive)